Changeset 284330 in webkit


Ignore:
Timestamp:
Oct 16, 2021 9:00:16 PM (9 months ago)
Author:
rmorisset@apple.com
Message:

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 size_t.
  • 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:
Location:
trunk
Files:
3 added
91 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r284237 r284330  
     12021-10-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        Allow WASM to use up to 4GB
     4        https://bugs.webkit.org/show_bug.cgi?id=229353
     5        rdar://81603447
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        The big-wasm-memory/wasm-memory-requested... tests used to simply expect an OOM at 2GB.
     10        They now expect success at 4GB, and failure at 4GB+1.
     11        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).
     12        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.
     13
     14        I also added a few new tests, specifically checking our handling of large typed arrays, and especially of indices above INT32_MAX.
     15
     16        * stress/big-wasm-memory-grow-no-max.js:
     17        (test):
     18        * stress/big-wasm-memory-grow.js:
     19        (test):
     20        * stress/big-wasm-memory.js:
     21        (test):
     22        * stress/typed-array-always-large.js: Added.
     23        (getArrayLength):
     24        (getByVal):
     25        (putByVal):
     26        (test):
     27        * stress/typed-array-eventually-large.js: Added.
     28        (getArrayLength):
     29        (getByVal):
     30        (putByVal):
     31        (test):
     32        * stress/typed-array-large-eventually-oob.js: Added.
     33        (getArrayLength):
     34        (getByVal):
     35        (putByVal):
     36        (test):
     37        * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js:
     38        * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js:
     39
    1402021-10-15  Robin Morisset  <rmorisset@apple.com>
    241
  • trunk/JSTests/stress/big-wasm-memory-grow-no-max.js

    r284237 r284330  
    1 //@ skip if $memoryLimited
     1//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
     2//@ runDefault()
    23
    34function test() {
     
    2526        foo(okArray);
    2627
     28    let maxSize = 0x10000;
     29    {
     30        var memory = new WebAssembly.Memory({ initial: 0x1000 });
     31        memory.grow(maxSize - 0x1000);
     32        var result = foo(new Uint8Array(memory.buffer));
     33        if (result !== void 0)
     34            throw "Error: bad result at end: " + result;
     35    }
     36
    2737    var ok = false;
    2838    try {
    2939        var memory = new WebAssembly.Memory({ initial: 0x1000 });
    30         memory.grow(0x7000);
     40        memory.grow(maxSize - 0x1000 + 1);
    3141        var result = foo(new Uint8Array(memory.buffer));
    32         if (result !== void 0)
    33             throw "Error: bad result at end: " + result;
    3442        ok = true;
    3543    } catch (e) {
    36         if (e.toString() != "RangeError: Out of memory")
     44        if (e.toString() != "RangeError: WebAssembly.Memory.grow expects the grown size to be a valid page count")
    3745            throw e;
    3846    }
    39 
    4047    if (ok)
    4148        throw "Error: did not throw error";
  • trunk/JSTests/stress/big-wasm-memory-grow.js

    r284237 r284330  
    1 //@ skip if $memoryLimited
     1//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
     2//@ runDefault()
    23
    34function test() {
     
    2526        foo(okArray);
    2627
    27     var ok = false;
    28     try {
    29         var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: 0x8000 });
    30         memory.grow(0x7000);
     28
     29    let maxSize = 0x10000;
     30    {
     31        var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize });
     32        memory.grow(maxSize - 0x1000);
    3133        var result = foo(new Uint8Array(memory.buffer));
    3234        if (result !== void 0)
    3335            throw "Error: bad result at end: " + result;
     36    }
     37
     38    var ok = false;
     39    try {
     40        var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize+1 });
     41        memory.grow(maxSize + 1 - 0x1000);
     42        var result = foo(new Uint8Array(memory.buffer));
    3443        ok = true;
    3544    } catch (e) {
    36         if (e.toString() != "RangeError: Out of memory")
     45        if (e.toString() != "RangeError: WebAssembly.Memory 'maximum' page count is too large")
    3746            throw e;
    3847    }
    39 
    4048    if (ok)
    4149        throw "Error: did not throw error";
  • trunk/JSTests/stress/big-wasm-memory.js

    r284237 r284330  
    1 //@ skip if $memoryLimited
     1//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
     2//@ runDefault()
    23
    34function test() {
     
    2526        foo(okArray);
    2627
     28    let maxSize = 0x10000;
     29    {
     30        var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize, maximum: maxSize }).buffer));
     31        if (result !== void 0)
     32            throw "Error: bad result at end: " + result;
     33    }
     34
    2735    var ok = false;
    2836    try {
    29         var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: 0x8000, maximum: 0x8000 }).buffer));
    30         if (result !== void 0)
    31             throw "Error: bad result at end: " + result;
     37        var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize+1, maximum: maxSize+1 }).buffer));
    3238        ok = true;
    3339    } catch (e) {
    34         if (e.toString() != "RangeError: Out of memory")
     40        if (e.toString() != "RangeError: WebAssembly.Memory 'initial' page count is too large")
    3541            throw e;
    3642    }
    37 
    3843    if (ok)
    3944        throw "Error: did not throw error";
  • trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js

    r284237 r284330  
    7777try {
    7878    var module = new WasmModuleBuilder();
    79     module.addMemory(32768);
     79    module.addMemory((2**16) + 1);
    8080    module.instantiate();
    8181} catch (e) {
     
    8383}
    8484
    85 if (exception != "RangeError: Out of memory") {
     85if (exception != "CompileError: WebAssembly.Module doesn't parse at byte 15: Memory's initial page count of 65537 is invalid (evaluating 'new WebAssembly.Module(this.toBuffer())')") {
    8686    print(exception);
    8787    throw "FAILED";
  • trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js

    r284237 r284330  
    22
    33try {
    4     new WebAssembly.Memory({ initial: 0x8000, maximum: 0x8000 }).buffer;
     4    new WebAssembly.Memory({ initial: 0x10001, maximum: 0x10001 }).buffer;
    55} catch (e) {
    66    exception = e;
    77}
    88
    9 if (exception != "RangeError: Out of memory")
    10     throw "FAILED";
     9if (exception != "RangeError: WebAssembly.Memory 'initial' page count is too large")
     10    throw "FAILED, exception was: " + exception;
  • trunk/LayoutTests/ChangeLog

    r284328 r284330  
     12021-10-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        Allow WASM to use up to 4GB
     4        https://bugs.webkit.org/show_bug.cgi?id=229353
     5        rdar://81603447
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        Rebaselined three following tests as different or fewer error messages appear on the console.
     10        Also changed currentVersion in serialized-script-value.html from 9 to 10.
     11
     12        * fast/canvas/canvas-getImageData-invalid-result-buffer-crash-expected.txt:
     13        * fast/storage/serialized-script-value.html:
     14        * webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt:
     15        * webaudio/OfflineAudioContext/bad-buffer-length-expected.txt:
     16
    1172021-10-16  Tim Horton  <timothy_horton@apple.com>
    218
  • trunk/LayoutTests/fast/storage/serialized-script-value.html

    r284237 r284330  
    77        <script>
    88
    9 const currentVersion = 0x09;
     9const currentVersion = 0x0a;
    1010
    1111// Here's a little Q&D helper for future adventurers needing to rebaseline this.
  • trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt

    r284237 r284330  
    1 CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.
    21This test passes if it does not crash.
    32
  • trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt

    r284237 r284330  
    1 CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.
    21Make sure that the length returned by OfflineAudioContext even if we failed to construct the rendering buffer.
    32
  • trunk/Source/JavaScriptCore/ChangeLog

    r284298 r284330  
     12021-10-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        Allow WASM to use up to 4GB
     4        https://bugs.webkit.org/show_bug.cgi?id=229353
     5        rdar://81603447
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work:
     10        - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being size_t.
     11        - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size.
     12            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)
     13        - Similarly, GetArrayLength and GetTypedArrayByteOffset now can either return an Int32 or a larger number.
     14            I also had to split them in the DFG/FTL, see GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 for examples
     15        - In turns, I had to add CheckInBoundsInt52 since CheckInBounds could not accept the result of GetTypedArrayLengthAsInt52
     16        - 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.
     17        - 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.
     18            I then updated the runtime functions used by the slow paths to correctly update it.
     19
     20        Unfortunately I ran out of time to add all the speculations/update all the fast paths.
     21        So the following will have to wait for a follow-up patch:
     22        - Accepting large indices in the fast path of GetByVal in the LLInt
     23        - Accepting large indices in the fast paths generated by AccessCase/PolymorphicAccess
     24        - Accepting large indices in the fast paths generated by the DFG/FTL for each of GetByVal/PutByVal/DataViewGet/DataViewSet/AtomicsXXX
     25
     26        The current patch is functional, it will just have dreadful performance if trying to use indices >2B in a {Int8/UInt8/UInt8Clamped}Array.
     27
     28        Other minor changes in this patch:
     29        - Fixed an undefined behavior in ArrayBuffer::createInternal where memcpy could be called on nullptr (the spec explicitly bans this even when length is 0)
     30        - 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.
     31        - Fixed a variety of obsolete comments
     32        - Added support for branch64(RelationalCondition cond, RegisterID left, Imm64 right)
     33            (there was already support for the same but with TrustedImm64)
     34        - Made various AbstractMacroAssembler function constexpr as part of the previous point
     35
     36        * assembler/AbstractMacroAssembler.cpp:
     37        * assembler/AbstractMacroAssembler.h:
     38        (JSC::AbstractMacroAssembler::TrustedImmPtr::TrustedImmPtr):
     39        (JSC::AbstractMacroAssembler::TrustedImmPtr::asIntptr):
     40        (JSC::AbstractMacroAssembler::TrustedImmPtr::asPtr):
     41        (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr):
     42        (JSC::AbstractMacroAssembler::ImmPtr::asTrustedImmPtr):
     43        (JSC::AbstractMacroAssembler::TrustedImm32::TrustedImm32):
     44        (JSC::AbstractMacroAssembler::Imm32::Imm32):
     45        (JSC::AbstractMacroAssembler::Imm32::asTrustedImm32 const):
     46        (JSC::AbstractMacroAssembler::TrustedImm64::TrustedImm64):
     47        (JSC::AbstractMacroAssembler::Imm64::Imm64):
     48        (JSC::AbstractMacroAssembler::Imm64::asTrustedImm64 const):
     49        (JSC::AbstractMacroAssembler::canBlind):
     50        (JSC::AbstractMacroAssembler::shouldBlindForSpecificArch):
     51        * assembler/MacroAssembler.h:
     52        (JSC::MacroAssembler::branch64):
     53        * assembler/MacroAssemblerARM64.h:
     54        (JSC::MacroAssemblerARM64::shouldBlindForSpecificArch):
     55        (JSC::MacroAssemblerARM64::branch64):
     56        * assembler/MacroAssemblerARM64E.h:
     57        (JSC::MacroAssemblerARM64E::untagArrayPtrLength64):
     58        (JSC::MacroAssemblerARM64E::untagArrayPtrLength32): Deleted.
     59        * assembler/MacroAssemblerX86Common.h:
     60        (JSC::MacroAssemblerX86Common::canBlind):
     61        (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch):
     62        * bytecode/AccessCase.cpp:
     63        (JSC::AccessCase::needsScratchFPR const):
     64        (JSC::AccessCase::generateWithGuard):
     65        * bytecode/ArrayProfile.h:
     66        (JSC::ArrayProfile::setMayBeLargeTypedArray):
     67        (JSC::ArrayProfile::mayBeLargeTypedArray const):
     68        (JSC::UnlinkedArrayProfile::UnlinkedArrayProfile):
     69        (JSC::UnlinkedArrayProfile::update):
     70        * dfg/DFGAbstractInterpreterInlines.h:
     71        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     72        * dfg/DFGArgumentsEliminationPhase.cpp:
     73        * dfg/DFGArrayMode.cpp:
     74        (JSC::DFG::ArrayMode::refine const):
     75        * dfg/DFGArrayMode.h:
     76        (JSC::DFG::ArrayMode::ArrayMode):
     77        (JSC::DFG::ArrayMode::mayBeLargeTypedArray const):
     78        (JSC::DFG::ArrayMode::withType const):
     79        (JSC::DFG::ArrayMode::withSpeculation const):
     80        (JSC::DFG::ArrayMode::withConversion const):
     81        (JSC::DFG::ArrayMode::withTypeAndConversion const):
     82        (JSC::DFG::ArrayMode::withArrayClassAndSpeculationAndMayBeLargeTypedArray const):
     83        (JSC::DFG::ArrayMode::speculationFromProfile):
     84        (JSC::DFG::ArrayMode::withSpeculationFromProfile const):
     85        (JSC::DFG::ArrayMode::withProfile const):
     86        (JSC::DFG::ArrayMode::operator== const):
     87        (JSC::DFG::ArrayMode::withArrayClass const): Deleted.
     88        * dfg/DFGByteCodeParser.cpp:
     89        (JSC::DFG::ByteCodeParser::handleIntrinsicGetter):
     90        * dfg/DFGClobberize.h:
     91        (JSC::DFG::clobberize):
     92        * dfg/DFGCommon.h:
     93        (JSC::DFG::enableInt52):
     94        * dfg/DFGConstantFoldingPhase.cpp:
     95        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     96        * dfg/DFGDoesGC.cpp:
     97        (JSC::DFG::doesGC):
     98        * dfg/DFGFixupPhase.cpp:
     99        (JSC::DFG::FixupPhase::fixupNode):
     100        (JSC::DFG::FixupPhase::convertToGetArrayLength):
     101        (JSC::DFG::FixupPhase::prependGetArrayLength): Deleted.
     102        * dfg/DFGGenerationInfo.h:
     103        * dfg/DFGHeapLocation.cpp:
     104        (WTF::printInternal):
     105        * dfg/DFGHeapLocation.h:
     106        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
     107        * dfg/DFGNode.h:
     108        (JSC::DFG::Node::hasStorageChild const):
     109        (JSC::DFG::Node::storageChildIndex):
     110        (JSC::DFG::Node::hasArrayMode):
     111        * dfg/DFGNodeType.h:
     112        * dfg/DFGOperations.cpp:
     113        (JSC::DFG::putByVal):
     114        (JSC::DFG::newTypedArrayWithSize):
     115        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
     116        * dfg/DFGOperations.h:
     117        * dfg/DFGPredictionPropagationPhase.cpp:
     118        * dfg/DFGSSALoweringPhase.cpp:
     119        (JSC::DFG::SSALoweringPhase::handleNode):
     120        (JSC::DFG::SSALoweringPhase::lowerBoundsCheck):
     121        * dfg/DFGSafeToExecute.h:
     122        (JSC::DFG::safeToExecute):
     123        * dfg/DFGSpeculativeJIT.cpp:
     124        (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
     125        (JSC::DFG::SpeculativeJIT::emitTypedArrayBoundsCheck):
     126        (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
     127        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
     128        (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
     129        (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
     130        (JSC::DFG::SpeculativeJIT::cageTypedArrayStorage):
     131        (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
     132        (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
     133        (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize):
     134        (JSC::DFG::SpeculativeJIT::emitNewTypedArrayWithSizeInRegister):
     135        (JSC::DFG::SpeculativeJIT::compileNewTypedArray):
     136        * dfg/DFGSpeculativeJIT.h:
     137        * dfg/DFGSpeculativeJIT32_64.cpp:
     138        (JSC::DFG::SpeculativeJIT::compileGetByVal):
     139        (JSC::DFG::SpeculativeJIT::compile):
     140        * dfg/DFGSpeculativeJIT64.cpp:
     141        (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithInt52Size):
     142        (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLengthAsInt52):
     143        (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52):
     144        (JSC::DFG::SpeculativeJIT::compile):
     145        * dfg/DFGTypeCheckHoistingPhase.cpp:
     146        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
     147        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
     148        * dfg/DFGValidate.cpp:
     149        * ftl/FTLCapabilities.cpp:
     150        (JSC::FTL::canCompile):
     151        * ftl/FTLLowerDFGToB3.cpp:
     152        (JSC::FTL::DFG::LowerDFGToB3::validateAIState):
     153        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     154        (JSC::FTL::DFG::LowerDFGToB3::emitGetTypedArrayByteOffsetExceptSettingResult):
     155        (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset):
     156        (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffsetAsInt52):
     157        (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
     158        (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayLengthAsInt52):
     159        (JSC::FTL::DFG::LowerDFGToB3::compileCheckInBoundsInt52):
     160        (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
     161        (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray):
     162        (JSC::FTL::DFG::LowerDFGToB3::emitNewTypedArrayWithSize):
     163        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
     164        * ftl/FTLOutput.h:
     165        (JSC::FTL::Output::load64NonNegative):
     166        * jit/IntrinsicEmitter.cpp:
     167        (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter):
     168        * jit/JITOperations.cpp:
     169        (JSC::putByVal):
     170        (JSC::getByVal):
     171        * llint/LLIntOfflineAsmConfig.h:
     172        * llint/LLIntSlowPaths.cpp:
     173        (JSC::LLInt::getByVal):
     174        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     175        * llint/LowLevelInterpreter.asm:
     176        * llint/LowLevelInterpreter32_64.asm:
     177        * llint/LowLevelInterpreter64.asm:
     178        * runtime/ArrayBuffer.cpp:
     179        (JSC::SharedArrayBufferContents::SharedArrayBufferContents):
     180        (JSC::ArrayBufferContents::ArrayBufferContents):
     181        (JSC::ArrayBufferContents::tryAllocate):
     182        (JSC::ArrayBuffer::create):
     183        (JSC::ArrayBuffer::createAdopted):
     184        (JSC::ArrayBuffer::createFromBytes):
     185        (JSC::ArrayBuffer::tryCreate):
     186        (JSC::ArrayBuffer::createUninitialized):
     187        (JSC::ArrayBuffer::tryCreateUninitialized):
     188        (JSC::ArrayBuffer::createInternal):
     189        (JSC::ArrayBuffer::clampValue):
     190        (JSC::ArrayBuffer::clampIndex const):
     191        (JSC::ArrayBuffer::sliceWithClampedIndex const):
     192        * runtime/ArrayBuffer.h:
     193        (JSC::ArrayBufferContents::sizeInBytes const):
     194        (JSC::ArrayBuffer::byteLength const):
     195        (JSC::ArrayBuffer::gcSizeEstimateInBytes const):
     196        * runtime/ArrayBufferView.cpp:
     197        (JSC::ArrayBufferView::ArrayBufferView):
     198        * runtime/ArrayBufferView.h:
     199        (JSC::ArrayBufferView::byteOffset const):
     200        (JSC::ArrayBufferView::byteLength const):
     201        (JSC::ArrayBufferView::verifyByteOffsetAlignment):
     202        (JSC::ArrayBufferView::verifySubRangeLength):
     203        (JSC::ArrayBufferView::clampOffsetAndNumElements):
     204        (JSC::ArrayBufferView::setImpl):
     205        (JSC::ArrayBufferView::setRangeImpl):
     206        (JSC::ArrayBufferView::getRangeImpl):
     207        (JSC::ArrayBufferView::zeroRangeImpl):
     208        (JSC::ArrayBufferView::calculateOffsetAndLength): Deleted.
     209        * runtime/AtomicsObject.cpp:
     210        * runtime/DataView.cpp:
     211        (JSC::DataView::DataView):
     212        (JSC::DataView::create):
     213        * runtime/DataView.h:
     214        * runtime/GenericTypedArrayView.h:
     215        * runtime/GenericTypedArrayViewInlines.h:
     216        (JSC::GenericTypedArrayView<Adaptor>::GenericTypedArrayView):
     217        (JSC::GenericTypedArrayView<Adaptor>::create):
     218        (JSC::GenericTypedArrayView<Adaptor>::tryCreate):
     219        (JSC::GenericTypedArrayView<Adaptor>::createUninitialized):
     220        (JSC::GenericTypedArrayView<Adaptor>::tryCreateUninitialized):
     221        (JSC::GenericTypedArrayView<Adaptor>::subarray const): Deleted.
     222        * runtime/JSArrayBufferView.cpp:
     223        (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext):
     224        (JSC::JSArrayBufferView::byteLength const):
     225        (JSC::JSArrayBufferView::slowDownAndWasteMemory):
     226        (JSC::JSArrayBufferView::possiblySharedImpl):
     227        * runtime/JSArrayBufferView.h:
     228        (JSC::JSArrayBufferView::sizeOf):
     229        (JSC::JSArrayBufferView::ConstructionContext::length const):
     230        (JSC::JSArrayBufferView::length const):
     231        * runtime/JSArrayBufferViewInlines.h:
     232        (JSC::JSArrayBufferView::byteOffsetImpl):
     233        (JSC::JSArrayBufferView::byteOffset):
     234        (JSC::JSArrayBufferView::byteOffsetConcurrently):
     235        * runtime/JSCJSValue.h:
     236        * runtime/JSCJSValueInlines.h:
     237        (JSC::JSValue::toIndex const):
     238        (JSC::JSValue::toTypedArrayIndex const):
     239        * runtime/JSDataView.cpp:
     240        (JSC::JSDataView::create):
     241        (JSC::JSDataView::createUninitialized):
     242        (JSC::JSDataView::set):
     243        (JSC::JSDataView::setIndex):
     244        * runtime/JSDataView.h:
     245        * runtime/JSDataViewPrototype.cpp:
     246        (JSC::getData):
     247        (JSC::setData):
     248        * runtime/JSGenericTypedArrayView.h:
     249        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
     250        (JSC::constructGenericTypedArrayViewWithArguments):
     251        (JSC::constructGenericTypedArrayViewImpl):
     252        * runtime/JSGenericTypedArrayViewInlines.h:
     253        (JSC::JSGenericTypedArrayView<Adaptor>::create):
     254        (JSC::JSGenericTypedArrayView<Adaptor>::createWithFastVector):
     255        (JSC::JSGenericTypedArrayView<Adaptor>::createUninitialized):
     256        (JSC::JSGenericTypedArrayView<Adaptor>::validateRange):
     257        (JSC::JSGenericTypedArrayView<Adaptor>::setWithSpecificType):
     258        (JSC::JSGenericTypedArrayView<Adaptor>::set):
     259        * runtime/JSObject.h:
     260        (JSC::JSObject::putByIndexInline):
     261        (JSC::JSObject::tryGetIndexQuickly const):
     262        (JSC::JSObject::trySetIndexQuickly):
     263        (JSC::JSObject::canSetIndexQuickly): Deleted.
     264        * runtime/JSObjectInlines.h:
     265        (JSC::JSObject::getIndexQuicklyForTypedArray const):
     266        (JSC::JSObject::setIndexQuicklyForArrayStorageIndexingType):
     267        (JSC::JSObject::trySetIndexQuicklyForTypedArray):
     268        (JSC::JSObject::canSetIndexQuicklyForTypedArray const): Deleted.
     269        * runtime/Operations.h:
     270        (JSC::getByValWithIndex):
     271        * wasm/WasmPageCount.h:
     272
    12732021-10-15  Ross Kirsling  <ross.kirsling@sony.com>
    2274
     
    362634
    363635        While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work:
    364         - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being UCPURegister.
     636        - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being size_t.
    365637        - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size.
    366638            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)
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r284237 r284330  
    266266    // from pointers used as absolute addresses to memory operations
    267267    struct TrustedImmPtr : public TrustedImm {
    268         TrustedImmPtr() { }
    269        
    270         explicit TrustedImmPtr(const void* value)
     268        constexpr TrustedImmPtr() { }
     269       
     270        explicit constexpr TrustedImmPtr(const void* value)
    271271            : m_value(value)
    272272        {
     
    279279        }
    280280
    281         explicit TrustedImmPtr(std::nullptr_t)
    282         {
    283         }
    284 
    285         explicit TrustedImmPtr(size_t value)
     281        explicit constexpr TrustedImmPtr(std::nullptr_t)
     282        {
     283        }
     284
     285        explicit constexpr TrustedImmPtr(size_t value)
    286286            : m_value(reinterpret_cast<void*>(value))
    287287        {
    288288        }
    289289
    290         intptr_t asIntptr()
     290        constexpr intptr_t asIntptr()
    291291        {
    292292            return reinterpret_cast<intptr_t>(m_value);
    293293        }
    294294
    295         void* asPtr()
     295        constexpr void* asPtr()
    296296        {
    297297            return const_cast<void*>(m_value);
     
    303303    struct ImmPtr : private TrustedImmPtr
    304304    {
    305         explicit ImmPtr(const void* value)
     305        explicit constexpr ImmPtr(const void* value)
    306306            : TrustedImmPtr(value)
    307307        {
    308308        }
    309309
    310         TrustedImmPtr asTrustedImmPtr() { return *this; }
     310        constexpr TrustedImmPtr asTrustedImmPtr() { return *this; }
    311311    };
    312312
     
    326326
    327327#if !CPU(X86_64)
    328         explicit TrustedImm32(TrustedImmPtr ptr)
     328        explicit constexpr TrustedImm32(TrustedImmPtr ptr)
    329329            : m_value(ptr.asIntptr())
    330330        {
     
    337337
    338338    struct Imm32 : private TrustedImm32 {
    339         explicit Imm32(int32_t value)
     339        explicit constexpr Imm32(int32_t value)
    340340            : TrustedImm32(value)
    341341        {
    342342        }
    343343#if !CPU(X86_64)
    344         explicit Imm32(TrustedImmPtr ptr)
     344        explicit constexpr Imm32(TrustedImmPtr ptr)
    345345            : TrustedImm32(ptr)
    346346        {
    347347        }
    348348#endif
    349         const TrustedImm32& asTrustedImm32() const { return *this; }
     349        constexpr const TrustedImm32& asTrustedImm32() const { return *this; }
    350350
    351351    };
     
    358358    // immediate values.
    359359    struct TrustedImm64 : TrustedImm {
    360         TrustedImm64() { }
    361        
    362         explicit TrustedImm64(int64_t value)
     360        constexpr TrustedImm64() { }
     361       
     362        explicit constexpr TrustedImm64(int64_t value)
    363363            : m_value(value)
    364364        {
     
    366366
    367367#if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
    368         explicit TrustedImm64(TrustedImmPtr ptr)
     368        explicit constexpr TrustedImm64(TrustedImmPtr ptr)
    369369            : m_value(ptr.asIntptr())
    370370        {
     
    377377    struct Imm64 : private TrustedImm64
    378378    {
    379         explicit Imm64(int64_t value)
     379        explicit constexpr Imm64(int64_t value)
    380380            : TrustedImm64(value)
    381381        {
    382382        }
    383383#if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
    384         explicit Imm64(TrustedImmPtr ptr)
     384        explicit constexpr Imm64(TrustedImmPtr ptr)
    385385            : TrustedImm64(ptr)
    386386        {
    387387        }
    388388#endif
    389         const TrustedImm64& asTrustedImm64() const { return *this; }
     389        constexpr const TrustedImm64& asTrustedImm64() const { return *this; }
    390390    };
    391391   
     
    10541054        return firstRegister();
    10551055    }
    1056     static bool canBlind() { return false; }
    1057     static bool shouldBlindForSpecificArch(uint32_t) { return false; }
    1058     static bool shouldBlindForSpecificArch(uint64_t) { return false; }
     1056    static constexpr bool canBlind() { return false; }
     1057    static constexpr bool shouldBlindForSpecificArch(uint32_t) { return false; }
     1058    static constexpr bool shouldBlindForSpecificArch(uint64_t) { return false; }
    10591059
    10601060    class CachedTempRegister {
  • trunk/Source/JavaScriptCore/assembler/MacroAssembler.h

    r284237 r284330  
    140140#if CPU(ARM64) || CPU(ARM_THUMB2) || CPU(X86_64) || CPU(MIPS) || CPU(RISCV64)
    141141    using MacroAssemblerBase::branchPtr;
     142#endif
     143#if CPU(X86_64)
     144    using MacroAssemblerBase::branch64;
    142145#endif
    143146    using MacroAssemblerBase::branchSub32;
     
    14611464            and64(imm.asTrustedImm32(), dest);
    14621465    }
     1466
    14631467#endif // USE(JSVALUE64)
    14641468
     
    17281732    }
    17291733
    1730 #endif // CPU(X86_64) || CPU(ARM64)
     1734#endif // CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
    17311735   
    17321736    void store32(Imm32 imm, Address dest)
     
    18211825        return branch32(cond, left, right.asTrustedImm32());
    18221826    }
     1827
     1828#if CPU(X86_64)
     1829    // Other 64-bit platforms don't need blinding, and have branch64(RelationalCondition, RegisterID, Imm64) directly defined in the right file.
     1830    // We cannot put this in MacroAssemblerX86_64.h, because it uses shouldBlind(), loadRoationBlindedConstant, etc.. which are only defined here and not there.
     1831    Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right)
     1832    {
     1833        if (shouldBlind(right)) {
     1834            if (haveScratchRegisterForBlinding()) {
     1835                loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegisterForBlinding());
     1836                return branch64(cond, left, scratchRegisterForBlinding());
     1837            }
     1838
     1839            // If we don't have a scratch register available for use, we'll just
     1840            // place a random number of nops.
     1841            uint32_t nopCount = random() & 3;
     1842            while (nopCount--)
     1843                nop();
     1844            return branch64(cond, left, right.asTrustedImm64());
     1845        }
     1846        return branch64(cond, left, right.asTrustedImm64());
     1847    }
     1848#endif // CPU(X86_64)
    18231849
    18241850    void compare32(RelationalCondition cond, RegisterID left, Imm32 right, RegisterID dest)
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r284237 r284330  
    145145
    146146    // FIXME: Get reasonable implementations for these
    147     static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
    148     static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
     147    static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
     148    static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
    149149
    150150    // Integer operations:
     
    33043304        }
    33053305        return Jump(makeBranch(cond));
     3306    }
     3307
     3308    Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right)
     3309    {
     3310        return branch64(cond, left, right.asTrustedImm64());
    33063311    }
    33073312
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h

    r284237 r284330  
    133133    }
    134134
    135     ALWAYS_INLINE void untagArrayPtrLength32(Address length, RegisterID target, bool validateAuth)
     135    ALWAYS_INLINE void untagArrayPtrLength64(Address length, RegisterID target, bool validateAuth)
    136136    {
    137137        auto lengthGPR = getCachedDataTempRegisterIDAndInvalidate();
    138         load32(length, lengthGPR);
     138        load64(length, lengthGPR);
    139139        auto scratch = validateAuth ? getCachedMemoryTempRegisterIDAndInvalidate() : InvalidGPRReg;
    140140        untagArrayPtr(lengthGPR, target, validateAuth, scratch);
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r284237 r284330  
    109109    static constexpr RegisterID framePointerRegister = X86Registers::ebp;
    110110   
    111     static bool canBlind() { return true; }
    112     static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
    113     static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
     111    static bool constexpr canBlind() { return true; }
     112    static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
     113    static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
    114114
    115115    // Integer arithmetic operations:
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp

    r284237 r284330  
    487487    case CustomValueSetter:
    488488    case CustomAccessorSetter:
    489     case IntrinsicGetter:
    490489    case InHit:
    491490    case InMiss:
     
    530529    case IndexedTypedArrayFloat32Store:
    531530    case IndexedTypedArrayFloat64Store:
     531    // Used by TypedArrayLength/TypedArrayByteOffset in the process of boxing their result as a double
     532    case IntrinsicGetter:
    532533        return true;
    533534    }
     
    11851186        GPRReg propertyGPR = state.u.propertyGPR;
    11861187
    1187        
    11881188        jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR);
    11891189        fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
    11901190
    1191         jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
    1192         state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR));
     1191        CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength());
     1192        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
     1193#if USE(LARGE_TYPED_ARRAYS)
     1194        // The length is a size_t, so either 32 or 64 bits depending on the platform.
     1195        state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength));
     1196#else
     1197        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength));
     1198#endif
    11931199
    11941200        auto allocator = state.makeDefaultScratchAllocator(scratchGPR);
     
    11981204            jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    11991205
     1206#if USE(LARGE_TYPED_ARRAYS)
     1207        jit.load64(addressOfLength, scratchGPR);
     1208#else
     1209        jit.load32(addressOfLength, scratchGPR);
     1210#endif
    12001211        jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
    12011212        jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
    1202 
    12031213        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
    12041214        if (isInt(type)) {
     
    15961606        }
    15971607
    1598         jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
    1599         // OutOfBounds bit of ArrayProfile will be set in the operation function.
    1600         state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR));
     1608        CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength());
     1609        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
     1610#if USE(LARGE_TYPED_ARRAYS)
     1611        // The length is a UCPURegister, so either 32 or 64 bits depending on the platform.
     1612        state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength));
     1613#else
     1614        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength));
     1615#endif
    16011616
    16021617        auto allocator = state.makeDefaultScratchAllocator(scratchGPR);
     
    16061621            jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
    16071622
     1623#if USE(LARGE_TYPED_ARRAYS)
     1624        jit.load64(addressOfLength, scratchGPR);
     1625#else
     1626        jit.load32(addressOfLength, scratchGPR);
     1627#endif
    16081628        jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
    16091629        jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
    1610 
    16111630        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
    16121631        if (isInt(type)) {
  • trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h

    r284237 r284330  
    3737// This is a bitfield where each bit represents an type of array access that we have seen.
    3838// There are 19 indexing types that use the lower bits.
    39 // There are 9 typed array types taking the bits 16 to 25.
     39// There are 11 typed array types taking the bits 16-20 and 26-31.
    4040typedef unsigned ArrayModes;
    4141
     
    206206    {
    207207    }
    208    
     208
     209#if USE(LARGE_TYPED_ARRAYS)
     210    static constexpr uint64_t s_smallTypedArrayMaxLength = std::numeric_limits<int32_t>::max();
     211    void setMayBeLargeTypedArray() { m_mayBeLargeTypedArray = true; }
     212    bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return m_mayBeLargeTypedArray; }
     213#else
     214    bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return false; }
     215#endif
     216
    209217    StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; }
    210218    ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
     
    245253    bool m_mayStoreToHole { false }; // This flag may become overloaded to indicate other special cases that were encountered during array access, as it depends on indexing type. Since we currently have basically just one indexing type (two variants of ArrayStorage), this flag for now just means exactly what its name implies.
    246254    bool m_outOfBounds { false };
     255#if USE(LARGE_TYPED_ARRAYS)
     256    bool m_mayBeLargeTypedArray { false };
     257#endif
    247258    bool m_mayInterceptIndexedAccesses : 1;
    248259    bool m_usesOriginalArrayStructures : 1;
     
    254265class UnlinkedArrayProfile {
    255266public:
    256     UnlinkedArrayProfile() = default;
     267    explicit UnlinkedArrayProfile()
     268        : m_usesOriginalArrayStructures(true)
     269#if USE(LARGE_TYPED_ARRAYS)
     270        , m_mayBeLargeTypedArray(false)
     271#endif
     272    {
     273    }
    257274
    258275    void update(ArrayProfile& arrayProfile)
     
    281298        else
    282299            m_usesOriginalArrayStructures = arrayProfile.m_usesOriginalArrayStructures;
     300
     301#if USE(LARGE_TYPED_ARRAYS)
     302        if (m_mayBeLargeTypedArray)
     303            arrayProfile.m_mayBeLargeTypedArray = true;
     304        else
     305            m_mayBeLargeTypedArray = arrayProfile.m_mayBeLargeTypedArray;
     306#endif
    283307    }
    284308
     
    291315    bool m_outOfBounds { false };
    292316    bool m_mayInterceptIndexedAccesses { false };
    293     bool m_usesOriginalArrayStructures { true };
     317    bool m_usesOriginalArrayStructures : 1;
     318#if USE(LARGE_TYPED_ARRAYS)
     319    bool m_mayBeLargeTypedArray : 1;
     320#endif
    294321};
     322static_assert(sizeof(UnlinkedArrayProfile) <= 8);
    295323
    296324} // namespace JSC
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r284237 r284330  
    34643464        JSArrayBufferView* view = m_graph.tryGetFoldableView(
    34653465            forNode(node->child1()).m_value, node->arrayMode());
     3466        if (view && isInBounds<int32_t>(view->length())) {
     3467            setConstant(node, jsNumber(view->length()));
     3468            break;
     3469        }
     3470        setNonCellTypeForNode(node, SpecInt32Only);
     3471        break;
     3472    }
     3473
     3474    case GetTypedArrayLengthAsInt52: {
     3475        JSArrayBufferView* view = m_graph.tryGetFoldableView(
     3476            forNode(node->child1()).m_value, node->arrayMode());
    34663477        if (view) {
    34673478            setConstant(node, jsNumber(view->length()));
    34683479            break;
    34693480        }
    3470         setNonCellTypeForNode(node, SpecInt32Only);
     3481        setNonCellTypeForNode(node, SpecInt52Any);
    34713482        break;
    34723483    }
     
    37973808        JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
    37983809        if (view) {
    3799             std::optional<unsigned> byteOffset = view->byteOffsetConcurrently();
     3810            std::optional<size_t> byteOffset = view->byteOffsetConcurrently();
     3811            if (byteOffset && isInBounds<int32_t>(byteOffset)) {
     3812                setConstant(node, jsNumber(*byteOffset));
     3813                break;
     3814            }
     3815        }
     3816        setNonCellTypeForNode(node, SpecInt32Only);
     3817        break;
     3818    }
     3819
     3820    case GetTypedArrayByteOffsetAsInt52: {
     3821        JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
     3822        if (view) {
     3823            std::optional<size_t> byteOffset = view->byteOffsetConcurrently();
    38003824            if (byteOffset) {
    38013825                setConstant(node, jsNumber(*byteOffset));
     
    38033827            }
    38043828        }
    3805         setNonCellTypeForNode(node, SpecInt32Only);
     3829        setNonCellTypeForNode(node, SpecInt52Any);
    38063830        break;
    38073831    }
     
    41074131        // thing to do here. We pick NodeResultJS because it makes converting this to an identity
    41084132        // easier.
     4133        setNonCellTypeForNode(node, SpecInt32Only);
     4134        break;
     4135    }
     4136    case CheckInBoundsInt52: {
     4137        // See the CheckInBounds case, it does not really matter what we put here.
    41094138        setNonCellTypeForNode(node, SpecInt32Only);
    41104139        break;
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp

    r284237 r284330  
    324324                    if ((node->child1()->op() == NewArrayWithSpread) && !node->origin.exitOK)
    325325                        escape(node->child1(), node);
     326                    break;
     327
     328                case GetTypedArrayLengthAsInt52:
     329                    // This node is only used for TypedArrays, so should not be relevant for arguments elimination
     330                    escape(node->child2(), node);
    326331                    break;
    327332
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r284237 r284330  
    210210    }
    211211   
    212     if (!isInt32Speculation(index))
     212    if (!isInt32Speculation(index) && !mayBeLargeTypedArray())
    213213        return ArrayMode(Array::Generic, action());
    214214   
     
    295295    case Array::BigInt64Array:
    296296    case Array::BigUint64Array:
     297        // FIXME: no idea why we only preserve this out-of-bounds information for PutByVal and not GetByVal as well.
     298        // https://bugs.webkit.org/show_bug.cgi?id=231276
    297299        if (node->op() == PutByVal) {
    298300            if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h

    r284237 r284330  
    128128        u.asBytes.conversion = Array::AsIs;
    129129        u.asBytes.action = Array::Write;
     130        u.asBytes.mayBeLargeTypedArray = false;
    130131    }
    131132   
     
    137138        u.asBytes.conversion = Array::AsIs;
    138139        u.asBytes.action = action;
     140        u.asBytes.mayBeLargeTypedArray = false;
    139141    }
    140142   
     
    146148        u.asBytes.conversion = Array::AsIs;
    147149        u.asBytes.action = action;
    148     }
    149    
    150     ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action)
     150        u.asBytes.mayBeLargeTypedArray = false;
     151    }
     152   
     153    ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action, bool mayBeLargeTypedArray = false)
    151154    {
    152155        u.asBytes.type = type;
     
    155158        u.asBytes.conversion = conversion;
    156159        u.asBytes.action = action;
     160        u.asBytes.mayBeLargeTypedArray = mayBeLargeTypedArray;
    157161    }
    158162   
     
    164168        u.asBytes.conversion = conversion;
    165169        u.asBytes.action = action;
     170        u.asBytes.mayBeLargeTypedArray = false;
    166171    }
    167172   
     
    171176    Array::Conversion conversion() const { return static_cast<Array::Conversion>(u.asBytes.conversion); }
    172177    Array::Action action() const { return static_cast<Array::Action>(u.asBytes.action); }
     178    bool mayBeLargeTypedArray() const { return u.asBytes.mayBeLargeTypedArray; }
    173179   
    174180    unsigned asWord() const { return u.asWord; }
     
    180186   
    181187    static ArrayMode fromObserved(const ConcurrentJSLocker&, ArrayProfile*, Array::Action, bool makeSafe);
    182    
     188
     189    ArrayMode withType(Array::Type type) const
     190    {
     191        return ArrayMode(type, arrayClass(), speculation(), conversion(), action(), mayBeLargeTypedArray());
     192    }
     193
    183194    ArrayMode withSpeculation(Array::Speculation speculation) const
    184195    {
    185         return ArrayMode(type(), arrayClass(), speculation, conversion(), action());
    186     }
    187    
    188     ArrayMode withArrayClass(Array::Class arrayClass) const
    189     {
    190         return ArrayMode(type(), arrayClass, speculation(), conversion(), action());
    191     }
    192    
     196        return ArrayMode(type(), arrayClass(), speculation, conversion(), action(), mayBeLargeTypedArray());
     197    }
     198
     199    ArrayMode withConversion(Array::Conversion conversion) const
     200    {
     201        return ArrayMode(type(), arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray());
     202    }
     203
     204    ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const
     205    {
     206        return ArrayMode(type, arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray());
     207    }
     208
     209    ArrayMode withArrayClassAndSpeculationAndMayBeLargeTypedArray(Array::Class arrayClass, Array::Speculation speculation, bool mayBeLargeTypedArray) const
     210    {
     211        return ArrayMode(type(), arrayClass, speculation, conversion(), action(), mayBeLargeTypedArray);
     212    }
     213
     214    static Array::Speculation speculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe)
     215    {
     216        if (makeSafe)
     217            return Array::OutOfBounds;
     218        else if (profile->mayStoreToHole(locker))
     219            return Array::ToHole;
     220        else
     221            return Array::InBounds;
     222    }
     223
    193224    ArrayMode withSpeculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
    194225    {
    195         Array::Speculation mySpeculation;
    196 
    197         if (makeSafe)
    198             mySpeculation = Array::OutOfBounds;
    199         else if (profile->mayStoreToHole(locker))
    200             mySpeculation = Array::ToHole;
    201         else
    202             mySpeculation = Array::InBounds;
    203        
    204         return withSpeculation(mySpeculation);
    205     }
    206    
     226        return withSpeculation(speculationFromProfile(locker, profile, makeSafe));
     227    }
     228
    207229    ArrayMode withProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
    208230    {
    209231        Array::Class myArrayClass;
    210 
    211232        if (isJSArray()) {
    212233            if (profile->usesOriginalArrayStructures(locker) && benefitsFromOriginalArray()) {
     
    222243        } else
    223244            myArrayClass = arrayClass();
    224        
    225         return withArrayClass(myArrayClass).withSpeculationFromProfile(locker, profile, makeSafe);
    226     }
    227    
    228     ArrayMode withType(Array::Type type) const
    229     {
    230         return ArrayMode(type, arrayClass(), speculation(), conversion(), action());
    231     }
    232    
    233     ArrayMode withConversion(Array::Conversion conversion) const
    234     {
    235         return ArrayMode(type(), arrayClass(), speculation(), conversion, action());
    236     }
    237    
    238     ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const
    239     {
    240         return ArrayMode(type, arrayClass(), speculation(), conversion, action());
     245
     246        Array::Speculation speculation = speculationFromProfile(locker, profile, makeSafe);
     247
     248        bool largeTypedArray = profile->mayBeLargeTypedArray(locker);
     249
     250        return withArrayClassAndSpeculationAndMayBeLargeTypedArray(myArrayClass, speculation, largeTypedArray);
    241251    }
    242252   
     
    527537            && arrayClass() == other.arrayClass()
    528538            && speculation() == other.speculation()
    529             && conversion() == other.conversion();
     539            && conversion() == other.conversion()
     540            && mayBeLargeTypedArray() == other.mayBeLargeTypedArray();
    530541    }
    531542   
     
    580591            uint8_t speculation;
    581592            uint8_t conversion : 4;
    582             uint8_t action : 4;
     593            uint8_t action : 1;
     594            uint8_t mayBeLargeTypedArray : 1;
    583595        } asBytes;
    584596        unsigned asWord;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r284237 r284330  
    38083808bool ByteCodeParser::handleIntrinsicGetter(Operand result, SpeculatedType prediction, const GetByVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
    38093809{
     3810#if USE(LARGE_TYPED_ARRAYS)
     3811    static_assert(enableInt52());
     3812#endif
     3813
    38103814    switch (variant.intrinsic()) {
    38113815    case TypedArrayByteLengthIntrinsic: {
     3816        bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
     3817#if !USE(LARGE_TYPED_ARRAYS)
     3818        if (willNeedGetTypedArrayLengthAsInt52)
     3819            return false;
     3820#endif
    38123821        insertChecks();
    38133822
     
    38233832        });
    38243833
    3825         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
     3834        NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength;
     3835        Node* lengthNode = addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
    38263836        // Our ArrayMode shouldn't cause us to exit here so we should be ok to exit without effects.
    38273837        m_exitOK = true;
    38283838        addToGraph(ExitOK);
    38293839
    3830 
    38313840        if (!logSize) {
    38323841            set(result, lengthNode);
     
    38343843        }
    38353844
    3836         // We can use a BitLShift here because typed arrays will never have a byteLength
    3837         // that overflows int32.
    3838         Node* shiftNode = jsConstant(jsNumber(logSize));
    3839         set(result, addToGraph(ArithBitLShift, lengthNode, shiftNode));
     3845        // We cannot use a BitLShift here because typed arrays may have a byteLength that overflows Int32.
     3846        Node* typeSize = jsConstant(jsNumber(1 << logSize));
     3847        set(result, addToGraph(ArithMul, lengthNode, typeSize));
    38403848
    38413849        return true;
     
    38433851
    38443852    case TypedArrayLengthIntrinsic: {
     3853        bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
     3854#if !USE(LARGE_TYPED_ARRAYS)
     3855        if (willNeedGetTypedArrayLengthAsInt52)
     3856            return false;
     3857#endif
    38453858        insertChecks();
    38463859
     
    38543867        });
    38553868
    3856         set(result, addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
     3869        NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength;
     3870        set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
    38573871
    38583872        return true;
     
    38613875
    38623876    case TypedArrayByteOffsetIntrinsic: {
     3877        bool willNeedGetTypedArrayByteOffsetAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
     3878#if !USE(LARGE_TYPED_ARRAYS)
     3879        if (willNeedGetTypedArrayByteOffsetAsInt52)
     3880            return false;
     3881#endif
    38633882        insertChecks();
    38643883
     
    38723891        });
    38733892
    3874         set(result, addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
     3893        NodeType op = willNeedGetTypedArrayByteOffsetAsInt52 ? GetTypedArrayByteOffsetAsInt52 : GetTypedArrayByteOffset;
     3894        set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
    38753895
    38763896        return true;
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    154154        case GetIndexedPropertyStorage:
    155155        case GetArrayLength:
     156        case GetTypedArrayLengthAsInt52:
    156157        case GetVectorLength:
    157158        case InByVal:
     
    240241    case LogicalNot:
    241242    case CheckInBounds:
     243    case CheckInBoundsInt52:
    242244    case DoubleRep:
    243245    case ValueRep:
     
    13381340        return;
    13391341
     1342    case GetTypedArrayByteOffsetAsInt52:
     1343        read(MiscFields);
     1344        def(HeapLocation(TypedArrayByteOffsetInt52Loc, MiscFields, node->child1()), LazyNode(node));
     1345        return;
     1346
    13401347    case GetPrototypeOf: {
    13411348        switch (node->child1().useKind()) {
     
    14431450            return;
    14441451        }
     1452    }
     1453
     1454    case GetTypedArrayLengthAsInt52: {
     1455        ArrayMode mode = node->arrayMode();
     1456        RELEASE_ASSERT(mode.isSomeTypedArrayView());
     1457        read(MiscFields);
     1458        def(HeapLocation(TypedArrayLengthInt52Loc, MiscFields, node->child1()), LazyNode(node));
     1459        return;
    14451460    }
    14461461
  • trunk/Source/JavaScriptCore/dfg/DFGCommon.h

    r284237 r284330  
    9393}
    9494
    95 inline bool enableInt52()
     95inline bool constexpr enableInt52()
    9696{
    9797#if USE(JSVALUE64)
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r284237 r284330  
    388388                break;
    389389            }
     390            case CheckInBoundsInt52:
     391                break;
    390392               
    391393            case GetMyArgumentByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r284237 r284330  
    186186    case AssertInBounds:
    187187    case CheckInBounds:
     188    case CheckInBoundsInt52:
    188189    case ConstantStoragePointer:
    189190    case Check:
     
    198199    case GetSetter:
    199200    case GetArrayLength:
     201    case GetTypedArrayLengthAsInt52:
    200202    case GetVectorLength:
    201203    case StringCharCodeAt:
    202204    case StringCodePointAt:
    203205    case GetTypedArrayByteOffset:
     206    case GetTypedArrayByteOffsetAsInt52:
    204207    case GetPrototypeOf:
    205208    case PutStructure:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    10441044                    && node->arrayMode().isSpecific()
    10451045                    && node->arrayMode().isInBounds()
     1046                    && !node->arrayMode().mayBeLargeTypedArray()
    10461047                    && !m_graph.hasExitSite(node->origin.semantic, Overflow)) {
    10471048
     
    10741075            case Array::ForceExit: {
    10751076                // Don't force OSR because we have only seen OwnStructureMode.
    1076                 // FIXME: WE should have a better way to do this...
     1077                // FIXME: We should have a better way to do this...
    10771078                if (node->op() == EnumeratorGetByVal)
    10781079                    node->setArrayMode(node->arrayMode().withType(Array::Generic));
     
    11341135                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
    11351136                break;
     1137            case Array::Int8Array:
     1138            case Array::Int16Array:
     1139            case Array::Int32Array:
     1140            case Array::Uint8Array:
     1141            case Array::Uint8ClampedArray:
     1142            case Array::Uint16Array:
     1143            case Array::Uint32Array:
     1144            case Array::Float32Array:
     1145            case Array::Float64Array:
     1146                fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
     1147                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
     1148                break;
    11361149            default:
    11371150                fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
     
    11851198                    && node->arrayMode().isSpecific()
    11861199                    && node->arrayMode().isInBounds()
     1200                    && !node->arrayMode().mayBeLargeTypedArray()
    11871201                    && !m_graph.hasExitSite(node->origin.semantic, Overflow)) {
    11881202
     
    17181732        case NewTypedArray: {
    17191733            watchHavingABadTime(node);
    1720            
    17211734            if (node->child1()->shouldSpeculateInt32()) {
    17221735                fixEdge<Int32Use>(node->child1());
     1736                node->clearFlags(NodeMustGenerate);
     1737                break;
     1738            }
     1739            if (node->child1()->shouldSpeculateInt52()) {
     1740                fixEdge<Int52RepUse>(node->child1());
    17231741                node->clearFlags(NodeMustGenerate);
    17241742                break;
     
    21502168        }
    21512169
     2170        case GetTypedArrayLengthAsInt52: {
     2171            ArrayMode arrayMode = node->arrayMode().refine(m_graph, node, node->child1()->prediction(), ArrayMode::unusedIndexSpeculatedType);
     2172            ASSERT(arrayMode.isSomeTypedArrayView());
     2173            node->setArrayMode(arrayMode);
     2174            blessArrayOperation(node->child1(), Edge(), node->child2(), lengthNeedsStorage);
     2175
     2176            fixEdge<KnownCellUse>(node->child1());
     2177            node->setResult(NodeResultInt52);
     2178            break;
     2179        }
     2180
     2181        case GetTypedArrayByteOffsetAsInt52: {
     2182            fixEdge<KnownCellUse>(node->child1());
     2183            node->setResult(NodeResultInt52);
     2184            break;
     2185        }
     2186
    21522187        case GetTypedArrayByteOffset: {
    21532188            fixEdge<KnownCellUse>(node->child1());
     
    21832218        case AssertInBounds:
    21842219        case CheckInBounds:
     2220        case CheckInBoundsInt52:
    21852221        case ConstantStoragePointer:
    21862222        case DoubleAsInt32:
     
    40974133        node->child2() = Edge(storage);
    40984134    }
    4099    
    4100     Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
    4101     {
    4102         Node* storage = checkArray(arrayMode, origin, child, nullptr, lengthNeedsStorage);
    4103         return m_insertionSet.insertNode(
    4104             m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
    4105             OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
    4106     }
    41074135
    41084136    void convertToHasIndexedProperty(Node* node)
  • trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h

    r284237 r284330  
    4040// Can provide information as to whether a value is in machine registers, and if so which,
    4141// whether a value has been spilled to the RegisterFile, and if so may be able to provide
    42 // details of the format in memory (all values are spilled in a boxed form, but we may be
    43 // able to track the type of box), and tracks how many outstanding uses of a value remain,
     42// details of the format in memory, and tracks how many outstanding uses of a value remain,
    4443// so that we know when the value is dead and the machine registers associated with it
    4544// may be released.
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r284237 r284330  
    183183        return;
    184184
     185    case TypedArrayByteOffsetInt52Loc:
     186        out.print("TypedArrayByteOffsetInt52Loc");
     187        return;
     188
     189    case TypedArrayLengthInt52Loc:
     190        out.print("TypedArrayLengthInt52Loc");
     191        return;
     192
    185193    case PrototypeLoc:
    186194        out.print("PrototypeLoc");
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h

    r284237 r284330  
    6868    StructureLoc,
    6969    TypedArrayByteOffsetLoc,
     70    TypedArrayByteOffsetInt52Loc,
     71    TypedArrayLengthInt52Loc,
    7072    PrototypeLoc,
    7173    StackLoc,
  • trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp

    r284237 r284330  
    13361336                    if (nonNegative && lessThanLength) {
    13371337                        executeNode(block->at(nodeIndex));
    1338                         if (UNLIKELY(Options::validateBoundsCheckElimination()))
     1338                        if (UNLIKELY(Options::validateBoundsCheckElimination()) && node->op() == CheckInBounds)
    13391339                            m_insertionSet.insertNode(nodeIndex, SpecNone, AssertInBounds, node->origin, node->child1(), node->child2());
    13401340                        // We just need to make sure we are a value-producing node.
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    19661966        case ArrayPop:
    19671967        case GetArrayLength:
     1968        case GetTypedArrayLengthAsInt52:
    19681969        case HasIndexedProperty:
    19691970        case EnumeratorNextUpdateIndexAndMode:
     
    20052006        case ArrayPop:
    20062007        case GetArrayLength:
     2008        case GetTypedArrayLengthAsInt52:
    20072009            return 2;
    20082010
     
    22772279        case GetIndexedPropertyStorage:
    22782280        case GetArrayLength:
     2281        case GetTypedArrayLengthAsInt52:
    22792282        case GetVectorLength:
    22802283        case InByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r284237 r284330  
    262262    macro(MultiDeleteByOffset, NodeMustGenerate | NodeResultJS) \
    263263    macro(GetArrayLength, NodeResultInt32) \
     264    /* This is only relevant for TypedArrays, as they are the only ones that can have a length that does not fit in 32 bits. */ \
     265    /* GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 change to returning Int52 in Fixup. Doing it before causes validation failures. */ \
     266    macro(GetTypedArrayLengthAsInt52, NodeResultJS) \
    264267    macro(GetVectorLength, NodeResultInt32) \
    265268    macro(GetTypedArrayByteOffset, NodeResultInt32) \
     269    macro(GetTypedArrayByteOffsetAsInt52, NodeResultJS) \
    266270    macro(GetScope, NodeResultJS) \
    267271    macro(SkipScope, NodeResultJS) \
     
    287291    macro(AssertInBounds, NodeMustGenerate) \
    288292    macro(CheckInBounds, NodeMustGenerate | NodeResultJS) \
     293    macro(CheckInBoundsInt52, NodeMustGenerate | NodeResultJS) \
    289294    macro(CheckIdent, NodeMustGenerate) \
    290295    macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r284237 r284330  
    9898    if (baseValue.isObject()) {
    9999        JSObject* object = asObject(baseValue);
    100         if (object->canSetIndexQuickly(index, value)) {
    101             object->setIndexQuickly(vm, index, value);
     100        if (object->trySetIndexQuickly(vm, index, value))
    102101            return;
    103         }
    104102
    105103        object->methodTable(vm)->putByIndex(object, globalObject, index, value, strict);
     
    176174
    177175template<typename ViewClass>
    178 char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, int32_t size, char* vector)
     176char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, intptr_t size, char* vector)
    179177{
    180178    auto scope = DECLARE_THROW_SCOPE(vm);
     
    184182        return nullptr;
    185183    }
    186    
     184
     185    static_assert(std::numeric_limits<intptr_t>::max() <= std::numeric_limits<size_t>::max());
     186    size_t unsignedSize = static_cast<size_t>(size);
     187
    187188    if (vector)
    188         return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, size, untagArrayPtr(vector, size)));
    189 
    190     RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, size)));
     189        return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, unsignedSize, untagArrayPtr(vector, unsignedSize)));
     190
     191    RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, unsignedSize)));
    191192}
    192193
     
    19091910}
    19101911
    1911 JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1912JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19121913{
    19131914    VM& vm = globalObject->vm();
     
    19251926}
    19261927
    1927 JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1928JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19281929{
    19291930    VM& vm = globalObject->vm();
     
    19411942}
    19421943
    1943 JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1944JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19441945{
    19451946    VM& vm = globalObject->vm();
     
    19571958}
    19581959
    1959 JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1960JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19601961{
    19611962    VM& vm = globalObject->vm();
     
    19731974}
    19741975
    1975 JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1976JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19761977{
    19771978    VM& vm = globalObject->vm();
     
    19891990}
    19901991
    1991 JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     1992JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    19921993{
    19931994    VM& vm = globalObject->vm();
     
    20052006}
    20062007
    2007 JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     2008JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    20082009{
    20092010    VM& vm = globalObject->vm();
     
    20212022}
    20222023
    2023 JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     2024JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    20242025{
    20252026    VM& vm = globalObject->vm();
     
    20372038}
    20382039
    2039 JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     2040JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    20402041{
    20412042    VM& vm = globalObject->vm();
     
    20532054}
    20542055
    2055 JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     2056JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    20562057{
    20572058    VM& vm = globalObject->vm();
     
    20692070}
    20702071
    2071 JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
     2072JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
    20722073{
    20732074    VM& vm = globalObject->vm();
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r284237 r284330  
    120120JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, Butterfly*));
    121121JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSizeAndHint, char*, (JSGlobalObject*, Structure*, int32_t, int32_t, Butterfly*));
    122 JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     122JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    123123JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    124 JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     124JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    125125JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    126 JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     126JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    127127JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    128 JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     128JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    129129JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    130 JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     130JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    131131JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    132 JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     132JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    133133JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    134 JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     134JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    135135JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    136 JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     136JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    137137JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    138 JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     138JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    139139JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    140 JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     140JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    141141JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    142 JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
     142JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
    143143JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
    144144JSC_DECLARE_JIT_OPERATION(operationNewArrayIterator, JSCell*, (VM*, Structure*));
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r284237 r284330  
    987987        }
    988988
     989        case GetTypedArrayLengthAsInt52:
     990        case GetTypedArrayByteOffsetAsInt52: {
     991            setPrediction(SpecInt52Any);
     992            break;
     993        }
     994
    989995        case StringCharCodeAt:
    990996        case StringCodePointAt: {
     
    13211327        case AssertInBounds:
    13221328        case CheckInBounds:
     1329        case CheckInBoundsInt52:
    13231330        case ValueToInt32:
    13241331        case DoubleRep:
  • trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp

    r284237 r284330  
    101101           
    102102            if (m_node->arrayMode().typedArrayType() != NotTypedArray && m_node->arrayMode().isOutOfBounds()) {
    103                 Node* length = m_insertionSet.insertNode(
    104                     m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin,
    105                     OpInfo(m_node->arrayMode().asWord()), base, storage);
    106                
    107                 m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use);
     103#if USE(LARGE_TYPED_ARRAYS)
     104                if (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow)) {
     105                    Node* length = m_insertionSet.insertNode(
     106                        m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin,
     107                        OpInfo(m_node->arrayMode().asWord()), base, storage);
     108                    m_graph.varArgChild(m_node, 4) = Edge(length, Int52RepUse);
     109                } else {
     110#endif
     111                    Node* length = m_insertionSet.insertNode(
     112                        m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin,
     113                        OpInfo(m_node->arrayMode().asWord()), base, storage);
     114                    m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use);
     115#if USE(LARGE_TYPED_ARRAYS)
     116                }
     117#endif
    108118                break;
    109119            }
     
    138148        }
    139149
    140         Node* length = m_insertionSet.insertNode(
    141             m_nodeIndex, SpecInt32Only, op, m_node->origin,
    142             OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
    143         Node* checkInBounds = m_insertionSet.insertNode(
    144             m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin,
    145             index, Edge(length, KnownInt32Use));
     150        Node* checkInBounds;
     151#if USE(LARGE_TYPED_ARRAYS)
     152        if ((op == GetArrayLength) && (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow))) {
     153            Node* length = m_insertionSet.insertNode(
     154                m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin,
     155                OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
     156            length->setResult(NodeResultInt52);
     157            // The return type is a dummy since this node does not actually return anything.
     158            checkInBounds = m_insertionSet.insertNode(
     159                m_nodeIndex, SpecInt32Only, CheckInBoundsInt52, m_node->origin,
     160                index, Edge(length, Int52RepUse));
     161        } else {
     162#endif
     163            Node* length = m_insertionSet.insertNode(
     164                m_nodeIndex, SpecInt32Only, op, m_node->origin,
     165                OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
     166            checkInBounds = m_insertionSet.insertNode(
     167                m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin,
     168                index, Edge(length, KnownInt32Use));
     169#if USE(LARGE_TYPED_ARRAYS)
     170        }
     171#endif
     172
    146173
    147174        AdjacencyList adjacencyList = m_graph.copyVarargChildren(m_node);
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r284237 r284330  
    289289    case AssertInBounds:
    290290    case CheckInBounds:
     291    case CheckInBoundsInt52:
    291292    case ConstantStoragePointer:
    292293    case Check:
     
    374375    case GetIndexedPropertyStorage:
    375376    case GetArrayLength:
     377    case GetTypedArrayLengthAsInt52:
    376378    case GetVectorLength:
    377379    case ArrayPop:
     
    386388    case CheckDetached:
    387389    case GetTypedArrayByteOffset:
     390    case GetTypedArrayByteOffsetAsInt52:
    388391        return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
    389392           
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r284237 r284330  
    32393239}
    32403240
    3241 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR)
     3241JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR)
    32423242{
    32433243    if (node->op() == PutByValAlias)
     
    32463246        m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode());
    32473247    if (view) {
    3248         uint32_t length = view->length();
     3248        size_t length = view->length();
    32493249        Node* indexNode = m_jit.graph().child(node, 1).node();
    3250         if (indexNode->isInt32Constant() && indexNode->asUInt32() < length)
     3250        if (indexNode->isAnyIntConstant() && indexNode->asUInt32() < length)
    32513251            return JITCompiler::Jump();
     3252#if USE(LARGE_TYPED_ARRAYS)
     3253        m_jit.signExtend32ToPtr(indexGPR, scratchGPR);
     3254        return m_jit.branch64(
     3255            MacroAssembler::AboveOrEqual, scratchGPR, MacroAssembler::Imm64(length));
     3256#else
     3257        UNUSED_PARAM(scratchGPR);
    32523258        return m_jit.branch32(
    32533259            MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length));
    3254     }
     3260#endif
     3261    }
     3262
     3263#if USE(LARGE_TYPED_ARRAYS)
     3264    m_jit.signExtend32ToPtr(indexGPR, scratchGPR);
     3265    return m_jit.branch64(
     3266        MacroAssembler::AboveOrEqual, scratchGPR,
     3267        MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
     3268#else
    32553269    return m_jit.branch32(
    32563270        MacroAssembler::AboveOrEqual, indexGPR,
    32573271        MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
    3258 }
    3259 
    3260 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR)
    3261 {
    3262     JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR);
     3272#endif
     3273}
     3274
     3275void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR)
     3276{
     3277    JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR, scratchGPR);
    32633278    if (!jump.isSet())
    32643279        return;
     
    33813396    SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
    33823397    StorageOperand storage(this, m_graph.varArgChild(node, 2));
     3398    GPRTemporary scratch(this);
    33833399
    33843400    GPRReg baseReg = base.gpr();
    33853401    GPRReg propertyReg = property.gpr();
    33863402    GPRReg storageReg = storage.gpr();
     3403    GPRReg scratchGPR = scratch.gpr();
    33873404
    33883405    std::optional<FPRTemporary> fprTemp;
     
    33983415    bool shouldBox = format == DataFormatJS;
    33993416
    3400     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
     3417    emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR);
    34013418    loadFromIntTypedArray(storageReg, propertyReg, resultRegs.payloadGPR(), type);
    34023419    constexpr bool canSpeculate = true;
     
    35563573   
    35573574    StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
     3575    GPRTemporary scratch(this);
    35583576    GPRReg storageReg = storage.gpr();
    35593577   
     
    35883606    ASSERT(valueGPR != base);
    35893607    ASSERT(valueGPR != storageReg);
    3590     JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
     3608    JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratch.gpr());
    35913609
    35923610    switch (elementSize(type)) {
     
    36463664    SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
    36473665    StorageOperand storage(this, m_graph.varArgChild(node, 2));
     3666    GPRTemporary scratch(this);
    36483667
    36493668    GPRReg baseReg = base.gpr();
    36503669    GPRReg propertyReg = property.gpr();
    36513670    GPRReg storageReg = storage.gpr();
     3671    GPRReg scratchGPR = scratch.gpr();
    36523672
    36533673    JSValueRegs resultRegs;
     
    36573677    FPRTemporary result(this);
    36583678    FPRReg resultReg = result.fpr();
    3659     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
     3679    emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR);
    36603680    switch (elementSize(type)) {
    36613681    case 4:
     
    36913711    SpeculateDoubleOperand valueOp(this, valueUse);
    36923712    FPRTemporary scratch(this);
     3713    GPRTemporary gpScratch(this);
    36933714    FPRReg valueFPR = valueOp.fpr();
    36943715    FPRReg scratchFPR = scratch.fpr();
    3695 
    3696     MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
     3716    GPRReg scratchGPR = gpScratch.gpr();
     3717
     3718    MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratchGPR);
    36973719   
    36983720    switch (elementSize(type)) {
     
    79687990    auto untagArrayPtr = [&]() {
    79697991#if CPU(ARM64E)
    7970         m_jit.untagArrayPtrLength32(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth);
     7992        m_jit.untagArrayPtrLength64(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth);
    79717993#else
    79727994        UNUSED_PARAM(validateAuth);
     
    80408062    GPRReg vectorGPR = vector.gpr();
    80418063    GPRReg dataGPR = data.gpr();
    8042     ASSERT(baseGPR != vectorGPR);
    8043     ASSERT(baseGPR != dataGPR);
    8044     ASSERT(vectorGPR != dataGPR);
    80458064
    80468065    GPRReg arrayBufferGPR = dataGPR;
     
    80828101    ASSERT(!JSArrayBufferView::nullVectorPtr());
    80838102    nullVector.link(&m_jit);
     8103#endif
     8104
     8105#if USE(LARGE_TYPED_ARRAYS)
     8106    // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
     8107    speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::Above, vectorGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
    80848108#endif
    80858109
     
    83508374        GPRReg baseGPR = base.gpr();
    83518375        GPRReg resultGPR = result.gpr();
     8376#if USE(LARGE_TYPED_ARRAYS)
     8377        m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
     8378        speculationCheck(Overflow, JSValueSource(), nullptr, m_jit.branch64(MacroAssembler::Above, resultGPR, TrustedImm64(std::numeric_limits<int32_t>::max())));
     8379#else
    83528380        m_jit.load32(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
     8381#endif
    83538382        strictInt32Result(resultGPR, node);
    83548383        break;
    83558384    } }
    83568385}
     8386
    83578387
    83588388void SpeculativeJIT::compileCheckIdent(Node* node)
     
    1112011150    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
    1112111151    RELEASE_ASSERT(structure.get());
    11122    
     11152
     11153#if USE(LARGE_TYPED_ARRAYS)
     11154    // The operations we call on the slow path expect a intptr_t, so int64_t on 64 bit platforms
     11155    SpeculateInt32Operand size(this, node->child1());
     11156    GPRTemporary scratch(this);
     11157    GPRReg sizeGPR = size.gpr();
     11158    GPRReg scratchGPR = scratch.gpr();
     11159    m_jit.signExtend32ToPtr(sizeGPR, scratchGPR);
     11160    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, scratchGPR);
     11161#else
    1112311162    SpeculateInt32Operand size(this, node->child1());
    1112411163    GPRReg sizeGPR = size.gpr();
    11125    
     11164    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR);
     11165#endif
     11166}
     11167
     11168void SpeculativeJIT::emitNewTypedArrayWithSizeInRegister(Node* node, TypedArrayType typedArrayType, RegisteredStructure structure, GPRReg sizeGPR)
     11169{
    1112611170    GPRTemporary result(this);
    1112711171    GPRTemporary storage(this);
     
    1113711181    m_jit.move(TrustedImmPtr(nullptr), storageGPR);
    1113811182
     11183#if USE(LARGE_TYPED_ARRAYS)
     11184    slowCases.append(m_jit.branch64(
     11185        MacroAssembler::Above, sizeGPR, TrustedImm64(JSArrayBufferView::fastSizeLimit)));
     11186    // We assume through the rest of the fast path that the size is a 32-bit number.
     11187    static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit));
     11188#else
    1113911189    slowCases.append(m_jit.branch32(
    1114011190        MacroAssembler::Above, sizeGPR, TrustedImm32(JSArrayBufferView::fastSizeLimit)));
     11191#endif
    1114111192   
    1114211193    m_jit.move(sizeGPR, scratchGPR);
     
    1119411245        storageGPR,
    1119511246        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
     11247#if USE(LARGE_TYPED_ARRAYS)
     11248    m_jit.store64(
     11249        sizeGPR,
     11250        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
     11251#else
    1119611252    m_jit.store32(
    1119711253        sizeGPR,
    1119811254        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
     11255#endif
    1119911256    m_jit.store32(
    1120011257        TrustedImm32(FastTypedArray),
     
    1416814225        compileNewTypedArrayWithSize(node);
    1416914226        break;
     14227#if USE(LARGE_TYPED_ARRAYS)
     14228    case Int52RepUse:
     14229        compileNewTypedArrayWithInt52Size(node);
     14230        break;
     14231#endif
    1417014232    case UntypedUse: {
    1417114233        JSValueOperand argument(this, node->child1());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    13011301    void compileNewStringObject(Node*);
    13021302    void compileNewSymbol(Node*);
    1303    
     1303
     1304    void emitNewTypedArrayWithSizeInRegister(Node*, TypedArrayType, RegisteredStructure, GPRReg sizeGPR);
    13041305    void compileNewTypedArrayWithSize(Node*);
    1305    
     1306#if USE(LARGE_TYPED_ARRAYS)
     1307    void compileNewTypedArrayWithInt52Size(Node*);
     1308#endif
     1309
    13061310    void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
    13071311    void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
     
    13741378
    13751379    void compileGetArrayLength(Node*);
     1380#if USE(LARGE_TYPED_ARRAYS)
     1381    void compileGetTypedArrayLengthAsInt52(Node*);
     1382#endif
    13761383
    13771384    void compileCheckTypeInfoFlags(Node*);
     
    14321439    void compileConstantStoragePointer(Node*);
    14331440    void compileGetIndexedPropertyStorage(Node*);
    1434     JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
     1441    JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR);
    14351442    JITCompiler::Jump jumpForTypedArrayIsDetachedIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
    1436     void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
     1443    void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR);
    14371444    void compileGetTypedArrayByteOffset(Node*);
     1445#if USE(LARGE_TYPED_ARRAYS)
     1446    void compileGetTypedArrayByteOffsetAsInt52(Node*);
     1447#endif
    14381448    void compileGetByValOnIntTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
    14391449    void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
     
    24282438};
    24292439
    2430 // Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
     2440// Gives you a canonical Int52 (i.e. it's left-shifted by 12, low bits zero).
    24312441class SpeculateInt52Operand {
    24322442    WTF_MAKE_FAST_ALLOCATED;
     
    24762486};
    24772487
    2478 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
     2488// Gives you a strict Int52 (i.e. the payload is in the low 52 bits, high 12 bits are sign-extended).
    24792489class SpeculateStrictInt52Operand {
    24802490    WTF_MAKE_FAST_ALLOCATED;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r284255 r284330  
    21372137        break;
    21382138    default: {
     2139        ASSERT(node->arrayMode().isSomeTypedArrayView());
    21392140        TypedArrayType type = node->arrayMode().typedArrayType();
    21402141        if (isInt(type))
     
    35413542        break;
    35423543
     3544    case GetTypedArrayLengthAsInt52:
     3545        // We do not support typed arrays larger than 2GB on 32-bit platforms.
     3546        RELEASE_ASSERT_NOT_REACHED();
     3547        break;
     3548
    35433549    case DeleteById: {
    35443550        compileDeleteById(node);
     
    36203626    case GetTypedArrayByteOffset: {
    36213627        compileGetTypedArrayByteOffset(node);
     3628        break;
     3629    }
     3630
     3631    case GetTypedArrayByteOffsetAsInt52: {
     3632        RELEASE_ASSERT_NOT_REACHED();
    36223633        break;
    36233634    }
     
    44014412    case AssertInBounds:
    44024413    case CheckInBounds:
     4414    case CheckInBoundsInt52:
    44034415    case ArithIMul:
    44044416    case MultiGetByOffset:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    26942694    } }
    26952695}
     2696
     2697#if USE(LARGE_TYPED_ARRAYS)
     2698void SpeculativeJIT::compileNewTypedArrayWithInt52Size(Node* node)
     2699{
     2700    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
     2701    auto typedArrayType = node->typedArrayType();
     2702    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
     2703    RELEASE_ASSERT(structure.get());
     2704
     2705    SpeculateStrictInt52Operand size(this, node->child1());
     2706    GPRReg sizeGPR = size.gpr();
     2707
     2708    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR);
     2709}
     2710
     2711void SpeculativeJIT::compileGetTypedArrayLengthAsInt52(Node* node)
     2712{
     2713    RELEASE_ASSERT(node->arrayMode().isSomeTypedArrayView());
     2714    SpeculateCellOperand base(this, node->child1());
     2715    GPRTemporary result(this, Reuse, base);
     2716    GPRReg baseGPR = base.gpr();
     2717    GPRReg resultGPR = result.gpr();
     2718    m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
     2719    static_assert(MAX_ARRAY_BUFFER_SIZE < (1ull << 52), "there is a risk that the size of a typed array won't fit in an Int52");
     2720    strictInt52Result(resultGPR, node);
     2721}
     2722
     2723void SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52(Node* node)
     2724{
     2725    SpeculateCellOperand base(this, node->child1());
     2726    GPRTemporary vector(this);
     2727    GPRTemporary data(this);
     2728
     2729    GPRReg baseGPR = base.gpr();
     2730    GPRReg vectorGPR = vector.gpr();
     2731    GPRReg dataGPR = data.gpr();
     2732
     2733    GPRReg arrayBufferGPR = dataGPR;
     2734
     2735    JITCompiler::Jump emptyByteOffset = m_jit.branch32(
     2736        MacroAssembler::NotEqual,
     2737        MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
     2738        TrustedImm32(WastefulTypedArray));
     2739
     2740    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
     2741
     2742    JITCompiler::Jump nullVector = m_jit.branchPtr(JITCompiler::Equal, vectorGPR, TrustedImmPtr(JSArrayBufferView::nullVectorPtr()));
     2743
     2744    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
     2745    m_jit.cageWithoutUntagging(Gigacage::JSValue, dataGPR);
     2746
     2747    cageTypedArrayStorage(baseGPR, vectorGPR);
     2748
     2749    m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR);
     2750    // FIXME: This needs caging.
     2751    // https://bugs.webkit.org/show_bug.cgi?id=175515
     2752    m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR);
     2753#if CPU(ARM64E)
     2754    m_jit.removeArrayPtrTag(dataGPR);
     2755#endif
     2756
     2757    m_jit.subPtr(dataGPR, vectorGPR);
     2758
     2759    JITCompiler::Jump done = m_jit.jump();
     2760
     2761#if CPU(ARM64E)
     2762    nullVector.link(&m_jit);
     2763#endif
     2764    emptyByteOffset.link(&m_jit);
     2765    m_jit.move(TrustedImmPtr(nullptr), vectorGPR);
     2766
     2767    done.link(&m_jit);
     2768#if !CPU(ARM64E)
     2769    ASSERT(!JSArrayBufferView::nullVectorPtr());
     2770    nullVector.link(&m_jit);
     2771#endif
     2772
     2773    strictInt52Result(vectorGPR, node);
     2774}
     2775#endif // USE(LARGE_TYPED_ARRAYS)
    26962776
    26972777void SpeculativeJIT::compile(Node* node)
     
    36453725        SpeculateCellOperand base(this, baseEdge);
    36463726        SpeculateStrictInt32Operand index(this, indexEdge);
     3727        GPRTemporary scratch (this);
    36473728
    36483729        baseGPR = base.gpr();
    36493730        indexGPR = index.gpr();
    36503731       
    3651         emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
     3732        emitTypedArrayBoundsCheck(node, baseGPR, indexGPR, scratch.gpr());
    36523733       
    36533734        GPRTemporary args[2];
     
    43824463        break;
    43834464
     4465    case GetTypedArrayLengthAsInt52:
     4466#if USE(ADDRESS64)
     4467        compileGetTypedArrayLengthAsInt52(node);
     4468#else
     4469        RELEASE_ASSERT_NOT_REACHED();
     4470#endif
     4471        break;
     4472
    43844473    case DeleteById: {
    43854474        compileDeleteById(node);
     
    44974586    case GetTypedArrayByteOffset: {
    44984587        compileGetTypedArrayByteOffset(node);
     4588        break;
     4589    }
     4590
     4591    case GetTypedArrayByteOffsetAsInt52: {
     4592#if USE(LARGE_TYPED_ARRAYS)
     4593        compileGetTypedArrayByteOffsetAsInt52(node);
     4594#else
     4595        RELEASE_ASSERT_NOT_REACHED();
     4596#endif
    44994597        break;
    45004598    }
     
    55905688        if (data.byteSize > 1)
    55915689            m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
     5690#if USE(LARGE_TYPED_ARRAYS)
     5691        speculationCheck(OutOfBounds, JSValueRegs(), node,
     5692            m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0)));
     5693        m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
     5694#else
     5695        // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after
    55925696        m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
     5697#endif
    55935698        speculationCheck(OutOfBounds, JSValueRegs(), node,
    55945699            m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
     
    57915896        if (data.byteSize > 1)
    57925897            m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
     5898#if USE(LARGE_TYPED_ARRAYS)
     5899        speculationCheck(OutOfBounds, JSValueRegs(), node,
     5900            m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0)));
     5901        m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
     5902#else
     5903        // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after
    57935904        m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
     5905#endif
    57945906        speculationCheck(OutOfBounds, JSValueRegs(), node,
    57955907            m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
     
    60436155    case AssertInBounds:
    60446156    case CheckInBounds:
     6157    case CheckInBoundsInt52:
    60456158    case ArithIMul:
    60466159    case MultiGetByOffset:
  • trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp

    r284237 r284330  
    280280                case PutByValAlias:
    281281                case GetArrayLength:
     282                case GetTypedArrayLengthAsInt52:
    282283                case CheckArray:
    283284                case CheckDetached:
    284285                case GetIndexedPropertyStorage:
    285286                case GetTypedArrayByteOffset:
     287                case GetTypedArrayByteOffsetAsInt52:
    286288                case Phantom:
    287289                case MovHint:
     
    360362                case PutByValAlias:
    361363                case GetArrayLength:
     364                case GetTypedArrayLengthAsInt52:
    362365                case GetIndexedPropertyStorage:
    363366                case Phantom:
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r284237 r284330  
    641641                case AssertInBounds:
    642642                case CheckInBounds:
     643                case CheckInBoundsInt52:
    643644                case PhantomNewObject:
    644645                case PhantomNewFunction:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r284237 r284330  
    171171    case NukeStructureAndSetButterfly:
    172172    case GetTypedArrayByteOffset:
     173    case GetTypedArrayByteOffsetAsInt52:
    173174    case GetPrototypeOf:
    174175    case NotifyWrite:
     
    200201    case AssertInBounds:
    201202    case CheckInBounds:
     203    case CheckInBoundsInt52:
    202204    case ConstantStoragePointer:
    203205    case Check:
     
    392394    case CPUIntrinsic:
    393395    case GetArrayLength:
     396    case GetTypedArrayLengthAsInt52:
    394397    case GetVectorLength:
    395398    case GetByVal:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r284237 r284330  
    606606            if (node->op() == CheckInBounds)
    607607                continue;
     608            if (node->op() == CheckInBoundsInt52)
     609                continue;
    608610
    609611            AbstractValue value = m_interpreter.forNode(node);
     
    10261028            compileGetArrayLength();
    10271029            break;
     1030        case GetTypedArrayLengthAsInt52:
     1031            compileGetTypedArrayLengthAsInt52();
     1032            break;
    10281033        case GetVectorLength:
    10291034            compileGetVectorLength();
     
    10341039        case CheckInBounds:
    10351040            compileCheckInBounds();
     1041            break;
     1042        case CheckInBoundsInt52:
     1043            compileCheckInBoundsInt52();
    10361044            break;
    10371045        case GetByVal:
     
    11751183        case GetTypedArrayByteOffset:
    11761184            compileGetTypedArrayByteOffset();
     1185            break;
     1186        case GetTypedArrayByteOffsetAsInt52:
     1187            compileGetTypedArrayByteOffsetAsInt52();
    11771188            break;
    11781189        case GetPrototypeOf:
     
    48294840    }
    48304841
    4831     void compileGetTypedArrayByteOffset()
    4832     {
    4833         LValue basePtr = lowCell(m_node->child1());   
     4842    LValue emitGetTypedArrayByteOffsetExceptSettingResult()
     4843    {
     4844        LValue basePtr = lowCell(m_node->child1());
    48344845
    48354846        LBasicBlock wastefulCase = m_out.newBlock();
     
    48474858
    48484859        LValue vector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector);
    4849         m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())), 
     4860        m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())),
    48504861            unsure(continuation), unsure(notNull));
    48514862
     
    48674878        m_out.appendTo(continuation, lastNext);
    48684879
    4869         setInt32(m_out.castToInt32(m_out.phi(pointerType(), nullVectorOut, wastefulOut)));
    4870     }
     4880        return m_out.phi(pointerType(), nullVectorOut, wastefulOut);
     4881    }
     4882
     4883    void compileGetTypedArrayByteOffset()
     4884    {
     4885        LValue result = emitGetTypedArrayByteOffsetExceptSettingResult();
     4886#if USE(LARGE_TYPED_ARRAYS)
     4887        // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
     4888        speculate(Overflow, noValue(), nullptr, m_out.above(result, m_out.constInt64(std::numeric_limits<int32_t>::max())));
     4889#endif
     4890        setInt32(m_out.castToInt32(result));
     4891    }
     4892
     4893IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
     4894    void compileGetTypedArrayByteOffsetAsInt52()
     4895    {
     4896        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
     4897        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
     4898        LValue result = emitGetTypedArrayByteOffsetExceptSettingResult();
     4899        setStrictInt52(result);
     4900    }
     4901IGNORE_CLANG_WARNINGS_END
    48714902
    48724903    void compileGetPrototypeOf()
     
    50555086        default:
    50565087            if (m_node->arrayMode().isSomeTypedArrayView()) {
    5057                 setInt32(
    5058                     m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
     5088#if USE(LARGE_TYPED_ARRAYS)
     5089                LValue length = m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length);
     5090                speculate(Overflow, noValue(), nullptr, m_out.above(length, m_out.constInt64(std::numeric_limits<int32_t>::max())));
     5091                setInt32(m_out.castToInt32(length));
     5092#else
     5093                setInt32(m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
     5094#endif
    50595095                return;
    50605096            }
     
    50645100        }
    50655101    }
     5102
     5103IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
     5104    void compileGetTypedArrayLengthAsInt52()
     5105    {
     5106        RELEASE_ASSERT(m_node->arrayMode().isSomeTypedArrayView());
     5107        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
     5108        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
     5109        setStrictInt52(m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
     5110    }
     5111IGNORE_CLANG_WARNINGS_END
    50665112
    50675113    void compileGetVectorLength()
     
    51095155        // we dominate them.
    51105156    }
    5111    
     5157
     5158IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
     5159    void compileCheckInBoundsInt52()
     5160    {
     5161        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
     5162        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
     5163        // Sign-extended to also catch negative indices
     5164        LValue index = m_out.signExt32To64(lowInt32(m_node->child1()));
     5165        LValue length = lowStrictInt52(m_node->child2());
     5166        speculate(OutOfBounds, noValue(), nullptr, m_out.aboveOrEqual(index, length));
     5167        // Even though we claim to have JSValue result, no user of us should
     5168        // depend on our value. Users of this node just need to maintain that
     5169        // we dominate them.
     5170    }
     5171IGNORE_CLANG_WARNINGS_END
     5172
    51125173    LValue compileGetByValImpl()
    51135174    {
     
    60096070                    LBasicBlock isOutOfBounds = m_out.newBlock();
    60106071                    LBasicBlock continuation = m_out.newBlock();
    6011                    
    6012                     m_out.branch(
    6013                         m_out.aboveOrEqual(index, lowInt32(child5)),
    6014                         unsure(isOutOfBounds), unsure(isInBounds));
    6015                    
     6072
     6073                    LValue isOutOfBoundsCondition;
     6074                    if (child5.useKind() == Int52RepUse) {
     6075                        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
     6076                        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
     6077                        isOutOfBoundsCondition = m_out.aboveOrEqual(m_out.signExt32To64(index), lowStrictInt52(child5));
     6078                    } else {
     6079                        ASSERT(child5.useKind() == Int32Use);
     6080                        isOutOfBoundsCondition = m_out.aboveOrEqual(index, lowInt32(child5));
     6081                    }
     6082                    m_out.branch(isOutOfBoundsCondition, unsure(isOutOfBounds), unsure(isInBounds));
     6083
    60166084                    LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds);
    60176085                    m_out.store(valueToStore, pointer, storeType(type));
     
    81708238            RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
    81718239
    8172             LValue size = lowInt32(m_node->child1());
    8173 
    8174             LBasicBlock smallEnoughCase = m_out.newBlock();
    8175             LBasicBlock slowCase = m_out.newBlock();
    8176             LBasicBlock continuation = m_out.newBlock();
    8177            
    8178             ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero);
    8179 
    8180             m_out.branch(
    8181                 m_out.above(size, m_out.constInt32(JSArrayBufferView::fastSizeLimit)),
    8182                 rarely(slowCase), usually(smallEnoughCase));
    8183 
    8184             LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase);
    8185 
    8186             LValue byteSize =
    8187                 m_out.shl(m_out.zeroExtPtr(size), m_out.constInt32(logElementSize(typedArrayType)));
    8188             if (elementSize(typedArrayType) < 8) {
    8189                 byteSize = m_out.bitAnd(
    8190                     m_out.add(byteSize, m_out.constIntPtr(7)),
    8191                     m_out.constIntPtr(~static_cast<intptr_t>(7)));
    8192             }
    8193        
    8194             LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase);
    8195             LValue storage = allocateHeapCell(allocator, slowCase);
    8196            
    8197             splatWords(
    8198                 storage,
    8199                 m_out.int32Zero,
    8200                 m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))),
    8201                 m_out.int64Zero,
    8202                 m_heaps.typedArrayProperties);
    8203 
    8204 #if CPU(ARM64E)
    8205             {
    8206                 LValue sizePtr = m_out.zeroExtPtr(size);
    8207                 PatchpointValue* authenticate = m_out.patchpoint(pointerType());
    8208                 authenticate->appendSomeRegister(storage);
    8209                 authenticate->append(sizePtr, B3::ValueRep(B3::ValueRep::SomeLateRegister));
    8210                 authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
    8211                     jit.move(params[1].gpr(), params[0].gpr());
    8212                     jit.tagArrayPtr(params[2].gpr(), params[0].gpr());
    8213                 });
    8214                 storage = authenticate;
    8215             }
    8216 #endif
    8217 
    8218             ValueFromBlock haveStorage = m_out.anchor(storage);
    8219 
    8220             LValue fastResultValue = nullptr;
    8221             switch (typedArrayType) {
    8222 #define TYPED_ARRAY_TYPE_CASE(name) \
    8223             case Type ## name: \
    8224                 fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \
    8225                 break;
    8226             FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE)
    8227 #undef TYPED_ARRAY_TYPE_CASE
    8228             case TypeDataView:
    8229                 fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase);
    8230                 break;
    8231             default:
    8232                 RELEASE_ASSERT_NOT_REACHED();
    8233                 break;
    8234             }
    8235 
    8236             m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
    8237             m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
    8238             m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
    8239            
    8240             mutatorFence();
    8241             ValueFromBlock fastResult = m_out.anchor(fastResultValue);
    8242             m_out.jump(continuation);
    8243 
    8244             m_out.appendTo(slowCase, continuation);
    8245             LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage);
    8246 
    8247             VM& vm = this->vm();
    8248             LValue slowResultValue = lazySlowPath(
    8249                 [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
    8250                     return createLazyCallGenerator(vm,
    8251                         operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject,
    8252                         CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
    8253                         locations[2].directGPR());
    8254                 },
    8255                 size, storageValue);
    8256             ValueFromBlock slowResult = m_out.anchor(slowResultValue);
    8257             m_out.jump(continuation);
    8258 
    8259             m_out.appendTo(continuation, lastNext);
    8260             setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
     8240            LValue size = m_out.signExt32To64(lowInt32(m_node->child1()));
     8241
     8242            emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size);
     8243            return;
     8244        }
     8245
     8246        case Int52RepUse: {
     8247            RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
     8248
     8249            LValue size = lowStrictInt52(m_node->child1());
     8250
     8251            emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size);
    82618252            return;
    82628253        }
     
    82788269        }
    82798270    }
    8280    
     8271
     8272    void emitNewTypedArrayWithSize(TypedArrayType typedArrayType, JSGlobalObject* globalObject, RegisteredStructure structure, LValue size64Bits)
     8273    {
     8274        LBasicBlock smallEnoughCase = m_out.newBlock();
     8275        LBasicBlock slowCase = m_out.newBlock();
     8276        LBasicBlock continuation = m_out.newBlock();
     8277
     8278        ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero);
     8279
     8280        m_out.branch(
     8281            m_out.above(size64Bits, m_out.constInt64(JSArrayBufferView::fastSizeLimit)),
     8282            rarely(slowCase), usually(smallEnoughCase));
     8283
     8284        LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase);
     8285        // We assume through the rest of the fast path that the size is a 32-bit number.
     8286        static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit));
     8287
     8288        LValue byteSize =
     8289            m_out.shl(size64Bits, m_out.constInt32(logElementSize(typedArrayType)));
     8290        if (elementSize(typedArrayType) < 8) {
     8291            byteSize = m_out.bitAnd(
     8292                m_out.add(byteSize, m_out.constIntPtr(7)),
     8293                m_out.constIntPtr(~static_cast<intptr_t>(7)));
     8294        }
     8295
     8296        LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase);
     8297        LValue storage = allocateHeapCell(allocator, slowCase);
     8298
     8299        splatWords(
     8300            storage,
     8301            m_out.int32Zero,
     8302            m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))),
     8303            m_out.int64Zero,
     8304            m_heaps.typedArrayProperties);
     8305
     8306#if CPU(ARM64E)
     8307        {
     8308            PatchpointValue* authenticate = m_out.patchpoint(pointerType());
     8309            authenticate->appendSomeRegister(storage);
     8310            authenticate->append(size64Bits, B3::ValueRep(B3::ValueRep::SomeLateRegister));
     8311            authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     8312                jit.move(params[1].gpr(), params[0].gpr());
     8313                jit.tagArrayPtr(params[2].gpr(), params[0].gpr());
     8314            });
     8315            storage = authenticate;
     8316        }
     8317#endif
     8318
     8319        ValueFromBlock haveStorage = m_out.anchor(storage);
     8320
     8321        LValue fastResultValue = nullptr;
     8322        switch (typedArrayType) {
     8323#define TYPED_ARRAY_TYPE_CASE(name) \
     8324        case Type ## name: \
     8325            fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \
     8326            break;
     8327        FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE)
     8328#undef TYPED_ARRAY_TYPE_CASE
     8329        case TypeDataView:
     8330            fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase);
     8331            break;
     8332        default:
     8333            RELEASE_ASSERT_NOT_REACHED();
     8334            break;
     8335        }
     8336
     8337        m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
     8338#if USE(LARGE_TYPED_ARRAYS)
     8339        m_out.store64(size64Bits, fastResultValue, m_heaps.JSArrayBufferView_length);
     8340#else
     8341        m_out.store32(m_out.castToInt32(size64Bits), fastResultValue, m_heaps.JSArrayBufferView_length);
     8342#endif
     8343        m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
     8344
     8345        mutatorFence();
     8346        ValueFromBlock fastResult = m_out.anchor(fastResultValue);
     8347        m_out.jump(continuation);
     8348
     8349        m_out.appendTo(slowCase, continuation);
     8350        LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage);
     8351
     8352        VM& vm = this->vm();
     8353        LValue slowResultValue = lazySlowPath(
     8354            [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
     8355                return createLazyCallGenerator(vm,
     8356                    operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject,
     8357                    CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
     8358                    locations[2].directGPR());
     8359            },
     8360            size64Bits, storageValue);
     8361        ValueFromBlock slowResult = m_out.anchor(slowResultValue);
     8362        m_out.jump(continuation);
     8363
     8364        m_out.appendTo(continuation, lastNext);
     8365        setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
     8366        return;
     8367    }
     8368
    82818369    void compileAllocatePropertyStorage()
    82828370    {
     
    1465714745    }
    1465814746
     14747    // base and value are 64-bits, begin and end are 32-bits
     14748    // stores value at every 64-bits word between base+begin*8 and base+end*8
    1465914749    void splatWords(LValue base, LValue begin, LValue end, LValue value, const AbstractHeap& heap)
    1466014750    {
     
    1559215682        DataViewData data = m_node->dataViewData();
    1559315683
     15684#if USE(LARGE_TYPED_ARRAYS)
     15685        speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0)));
     15686        LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length);
     15687#else
     15688        // No need for an explicit comparison of index to 0, the check against length catches that case
    1559415689        LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length));
     15690#endif
    1559515691        LValue indexToCheck = m_out.zeroExtPtr(index);
    1559615692        if (data.byteSize > 1)
     
    1573515831        DataViewData data = m_node->dataViewData();
    1573615832
     15833#if USE(LARGE_TYPED_ARRAYS)
     15834        speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0)));
     15835        LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length);
     15836#else
     15837        // No need for an explicit comparison of index to 0, the check against length catches that case
    1573715838        LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length));
     15839#endif
    1573815840        LValue indexToCheck = m_out.zeroExtPtr(index);
    1573915841        if (data.byteSize > 1)
     
    1723717339#if CPU(ARM64E)
    1723817340            if (kind == Gigacage::Primitive) {
     17341#if USE(ADDRESS64)
     17342                LValue size = m_out.load64(base, m_heaps.JSArrayBufferView_length);
     17343#else
    1723917344                LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length);
     17345#endif
    1724017346                return untagArrayPtr(taggedPtr, size);
    1724117347            }
  • trunk/Source/JavaScriptCore/ftl/FTLOutput.h

    r284237 r284330  
    330330    LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); }
    331331    LValue load32NonNegative(LValue base, const AbstractHeap& field) { return load32(base, field); }
     332    LValue load64NonNegative(LValue base, const AbstractHeap& field) { return load64(base, field); }
    332333
    333334    LValue equal(LValue, LValue);
  • trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8787    switch (intrinsic()) {
    8888    case TypedArrayLengthIntrinsic: {
     89#if USE(LARGE_TYPED_ARRAYS)
     90        jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
     91        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
     92#else
    8993        jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
    9094        jit.boxInt32(valueGPR, valueRegs);
     95#endif
    9196        state.succeed();
    9297        return;
     
    95100    case TypedArrayByteLengthIntrinsic: {
    96101        TypedArrayType type = structure()->classInfo()->typedArrayStorageType;
    97 
     102#if USE(LARGE_TYPED_ARRAYS)
     103        jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
     104        if (elementSize(type) > 1)
     105            jit.lshift64(TrustedImm32(logElementSize(type)), valueGPR);
     106        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
     107#else
    98108        jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
    99 
    100109        if (elementSize(type) > 1) {
    101             // We can use a bitshift here since we TypedArrays cannot have byteLength that overflows an int32.
    102             jit.lshift32(valueGPR, Imm32(logElementSize(type)), valueGPR);
     110            // We can use a bitshift here since on ADDRESS32 platforms TypedArrays cannot have byteLength that overflows an int32.
     111            jit.lshift32(TrustedImm32(logElementSize(type)), valueGPR);
    103112        }
    104 
    105113        jit.boxInt32(valueGPR, valueRegs);
     114#endif
    106115        state.succeed();
    107116        return;
     
    134143       
    135144        done.link(&jit);
    136        
     145
     146#if USE(LARGE_TYPED_ARRAYS)
     147        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
     148#else
    137149        jit.boxInt32(valueGPR, valueRegs);
     150#endif
    138151        state.succeed();
    139152        return;
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r284237 r284330  
    938938        if (baseValue.isObject()) {
    939939            JSObject* object = asObject(baseValue);
    940             if (object->canSetIndexQuickly(i, value)) {
    941                 object->setIndexQuickly(vm, i, value);
     940            if (object->trySetIndexQuickly(vm, i, value, arrayProfile))
    942941                return;
    943             }
    944942
    945943            if (arrayProfile)
     
    23432341    }
    23442342
    2345     if (std::optional<int32_t> index = subscript.tryGetAsInt32()) {
    2346         int32_t i = *index;
     2343    if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
     2344        uint32_t i = *index;
    23472345        if (isJSString(baseValue)) {
    2348             if (i >= 0 && asString(baseValue)->canGetIndex(i))
     2346            if (asString(baseValue)->canGetIndex(i))
    23492347                RELEASE_AND_RETURN(scope, asString(baseValue)->getIndex(globalObject, i));
    23502348            if (arrayProfile)
     
    23522350        } else if (baseValue.isObject()) {
    23532351            JSObject* object = asObject(baseValue);
    2354             if (object->canGetIndexQuickly(static_cast<uint32_t>(i)))
    2355                 return object->getIndexQuickly(i);
     2352            if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile))
     2353                return result;
    23562354
    23572355            bool skipMarkingOutOfBounds = false;
    23582356
    2359             if (object->indexingType() == ArrayWithContiguous && i >= 0 && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) {
     2357            if (object->indexingType() == ArrayWithContiguous
     2358                && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) {
    23602359                // FIXME: expand this to ArrayStorage, Int32, and maybe Double:
    23612360                // https://bugs.webkit.org/show_bug.cgi?id=182940
     
    23732372        }
    23742373
    2375         if (i >= 0)
    2376             RELEASE_AND_RETURN(scope, baseValue.get(globalObject, static_cast<uint32_t>(i)));
     2374        RELEASE_AND_RETURN(scope, baseValue.get(globalObject, i));
    23772375    } else if (subscript.isNumber() && baseValue.isCell() && arrayProfile)
    23782376        arrayProfile->setOutOfBounds();
  • trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h

    r284237 r284330  
    150150#endif
    151151
     152#if USE(LARGE_TYPED_ARRAYS)
     153#define OFFLINE_ASM_LARGE_TYPED_ARRAYS 1
     154#else
     155#define OFFLINE_ASM_LARGE_TYPED_ARRAYS 0
     156#endif
     157
    152158#if CPU(ADDRESS64)
    153159#define OFFLINE_ASM_ADDRESS64 1
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r284237 r284330  
    10481048        } else if (baseValue.isObject()) {
    10491049            JSObject* object = asObject(baseValue);
    1050             if (object->canGetIndexQuickly(i))
    1051                 return object->getIndexQuickly(i);
     1050            if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile))
     1051                return result;
    10521052
    10531053            bool skipMarkingOutOfBounds = false;
     
    11711171    JSValue value = getOperand(callFrame, bytecode.m_value);
    11721172    bool isStrictMode = bytecode.m_ecmaMode.isStrict();
     1173    auto& metadata = bytecode.metadata(codeBlock);
    11731174   
    11741175    if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
     
    11761177        if (baseValue.isObject()) {
    11771178            JSObject* object = asObject(baseValue);
    1178             if (object->canSetIndexQuickly(i, value))
    1179                 object->setIndexQuickly(vm, i, value);
    1180             else
     1179            if (!object->trySetIndexQuickly(vm, i, value, &metadata.m_arrayProfile))
    11811180                object->methodTable(vm)->putByIndex(object, globalObject, i, value, isStrictMode);
    11821181            LLINT_END();
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r284237 r284330  
    216216    const NumberOfStructureIDEntropyBits = constexpr StructureIDTable::s_numberOfEntropyBits
    217217    const StructureEntropyBitsShift = constexpr StructureIDTable::s_entropyBitsShiftForStructurePointer
     218end
     219
     220if LARGE_TYPED_ARRAYS
     221    const SmallTypedArrayMaxLength = constexpr ArrayProfile::s_smallTypedArrayMaxLength
    218222end
    219223
     
    13111315end
    13121316
    1313 macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, slowPath)
     1317# Note that index is already sign-extended to be a register width.
     1318macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, slowPath)
    13141319    # First lets check if we even have a typed array. This lets us do some boilerplate up front.
    13151320    loadb JSCell::m_type[base], t2
     
    13221327        const length = t6
    13231328        const scratch = t7
    1324         loadi JSArrayBufferView::m_length[base], length
    1325         biaeq index, length, slowPath
     1329        if LARGE_TYPED_ARRAYS
     1330            loadq JSArrayBufferView::m_length[base], length
     1331            bqaeq index, length, slowPath
     1332        else
     1333            loadi JSArrayBufferView::m_length[base], length
     1334            biaeq index, length, slowPath
     1335        end
    13261336    else
    13271337        # length and scratch are intentionally undefined on this branch because they are not used on other platforms.
    1328         biaeq index, JSArrayBufferView::m_length[base], slowPath
     1338        if LARGE_TYPED_ARRAYS
     1339            bqaeq index, JSArrayBufferView::m_length[base], slowPath
     1340        else
     1341            biaeq index, JSArrayBufferView::m_length[base], slowPath
     1342        end
     1343    end
     1344
     1345    if LARGE_TYPED_ARRAYS
     1346        bqbeq index, SmallTypedArrayMaxLength, .smallTypedArray
     1347        setLargeTypedArray()
     1348.smallTypedArray:
    13291349    end
    13301350
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r284255 r284330  
    16231623    end
    16241624
     1625    macro setLargeTypedArray()
     1626        crash()
     1627    end
     1628
    16251629    metadata(t5, t2)
    16261630    get(m_base, t2)
     
    16681672
    16691673.opGetByValNotIndexedStorage:
    1670     getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)
     1674    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow)
    16711675
    16721676.opGetByValSlow:
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r284237 r284330  
    17141714    end
    17151715
     1716    macro setLargeTypedArray()
     1717        if LARGE_TYPED_ARRAYS
     1718            storeb 1, OpGetByVal::Metadata::m_arrayProfile + ArrayProfile::m_mayBeLargeTypedArray[t5]
     1719        else
     1720            crash()
     1721        end
     1722    end
     1723
    17161724    metadata(t5, t2)
    17171725
     
    17241732    get(m_property, t3)
    17251733    loadConstantOrVariableInt32(size, t3, t1, .opGetByValSlow)
     1734    # This sign-extension makes the bounds-checking in getByValTypedArray work even on 4GB TypedArray.
    17261735    sxi2q t1, t1
    17271736
     
    17641773
    17651774.opGetByValNotIndexedStorage:
    1766     getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)
     1775    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow)
    17671776
    17681777.opGetByValSlow:
  • trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2009-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4343}
    4444
    45 SharedArrayBufferContents::SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&& destructor)
     45SharedArrayBufferContents::SharedArrayBufferContents(void* data, size_t size, ArrayBufferDestructorFunction&& destructor)
    4646    : m_data(data, size)
    4747    , m_destructor(WTFMove(destructor))
     
    6969}
    7070
    71 ArrayBufferContents::ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&& destructor)
     71ArrayBufferContents::ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&& destructor)
    7272    : m_data(data, sizeInBytes)
    7373    , m_sizeInBytes(sizeInBytes)
     
    110110}
    111111
    112 void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy policy)
    113 {
    114     // Do not allow 31-bit overflow of the total size.
    115     if (numElements) {
    116         unsigned totalSize = numElements * elementByteSize;
    117         if (totalSize / numElements != elementByteSize || totalSize > MAX_ARRAY_BUFFER_SIZE) {
    118             reset();
    119             return;
    120         }
    121     }
    122     size_t sizeInBytes = static_cast<size_t>(numElements) * static_cast<size_t>(elementByteSize);
    123     size_t allocationSize = sizeInBytes;
     112void ArrayBufferContents::tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy policy)
     113{
     114    CheckedSize sizeInBytes = numElements;
     115    sizeInBytes *= elementByteSize;
     116    if (sizeInBytes.hasOverflowed() || sizeInBytes.value() > MAX_ARRAY_BUFFER_SIZE) {
     117        reset();
     118        return;
     119    }
     120
     121    size_t allocationSize = sizeInBytes.value();
    124122    if (!allocationSize)
    125123        allocationSize = 1; // Make sure malloc actually allocates something, but not too much. We use null to mean that the buffer is detached.
    126124
    127125    void* data = Gigacage::tryMalloc(Gigacage::Primitive, allocationSize);
    128     m_data = DataType(data, sizeInBytes);
     126    m_data = DataType(data, sizeInBytes.value());
    129127    if (!data) {
    130128        reset();
     
    135133        memset(data, 0, allocationSize);
    136134
    137     m_sizeInBytes = sizeInBytes;
     135    m_sizeInBytes = sizeInBytes.value();
    138136    RELEASE_ASSERT(m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE);
    139137    m_destructor = ArrayBuffer::primitiveGigacageDestructor();
     
    179177}
    180178
    181 Ref<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
     179Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize)
    182180{
    183181    auto buffer = tryCreate(numElements, elementByteSize);
     
    192190}
    193191
    194 Ref<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
     192Ref<ArrayBuffer> ArrayBuffer::create(const void* source, size_t byteLength)
    195193{
    196194    auto buffer = tryCreate(source, byteLength);
     
    209207// - JSGenericTypedArrayView<>::slowDownAndWasteMemory. But in that case, the memory should have already come
    210208//   from the cage.
    211 Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsigned byteLength)
     209Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, size_t byteLength)
    212210{
    213211    ASSERT(!Gigacage::isEnabled() || (Gigacage::contains(data) && Gigacage::contains(static_cast<const uint8_t*>(data) + byteLength - 1)));
     
    221219//   differently.
    222220// - WebAssembly. Wasm should allocate from the cage.
    223 Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&& destructor)
     221Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&& destructor)
    224222{
    225223    if (data && !Gigacage::isCaged(Gigacage::Primitive, data))
     
    230228}
    231229
    232 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(unsigned numElements, unsigned elementByteSize)
     230RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize)
    233231{
    234232    return tryCreate(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize);
     
    240238}
    241239
    242 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, unsigned byteLength)
     240RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, size_t byteLength)
    243241{
    244242    ArrayBufferContents contents;
     
    249247}
    250248
    251 Ref<ArrayBuffer> ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize)
     249Ref<ArrayBuffer> ArrayBuffer::createUninitialized(size_t numElements, unsigned elementByteSize)
    252250{
    253251    return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
    254252}
    255253
    256 RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized(unsigned numElements, unsigned elementByteSize)
     254RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized(size_t numElements, unsigned elementByteSize)
    257255{
    258256    return tryCreate(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
    259257}
    260258
    261 Ref<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
     259Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
    262260{
    263261    auto buffer = tryCreate(numElements, elementByteSize, policy);
     
    267265}
    268266
    269 Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, unsigned byteLength)
    270 {
    271     ASSERT(!byteLength || source);
     267Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, size_t byteLength)
     268{
    272269    auto buffer = adoptRef(*new ArrayBuffer(WTFMove(contents)));
    273     memcpy(buffer->data(), source, byteLength);
     270    if (byteLength) {
     271        ASSERT(source);
     272        memcpy(buffer->data(), source, byteLength);
     273    }
    274274    return buffer;
    275275}
    276276
    277 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
     277RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
    278278{
    279279    ArrayBufferContents contents;
     
    292292}
    293293
    294 unsigned ArrayBuffer::clampValue(double x, unsigned left, unsigned right)
     294size_t ArrayBuffer::clampValue(double x, size_t left, size_t right)
    295295{
    296296    ASSERT(left <= right);
     
    302302}
    303303
    304 unsigned ArrayBuffer::clampIndex(double index) const
    305 {
    306     unsigned currentLength = byteLength();
     304size_t ArrayBuffer::clampIndex(double index) const
     305{
     306    size_t currentLength = byteLength();
    307307    if (index < 0)
    308308        index = currentLength + index;
     
    320320}
    321321
    322 RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(unsigned begin, unsigned end) const
    323 {
    324     unsigned size = begin <= end ? end - begin : 0;
     322RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(size_t begin, size_t end) const
     323{
     324    size_t size = begin <= end ? end - begin : 0;
    325325    auto result = ArrayBuffer::tryCreate(static_cast<const char*>(data()) + begin, size);
    326326    if (result)
  • trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3434#include <wtf/PackedRefPtr.h>
    3535#include <wtf/SharedTask.h>
     36#include <wtf/StdIntExtras.h>
    3637#include <wtf/StdLibExtras.h>
    3738#include <wtf/ThreadSafeRefCounted.h>
     
    4041namespace JSC {
    4142
     43#if USE(LARGE_TYPED_ARRAYS)
     44static_assert(sizeof(size_t) == sizeof(uint64_t));
     45#define MAX_ARRAY_BUFFER_SIZE (1ull << 32)
     46#else
     47static_assert(sizeof(size_t) == sizeof(uint32_t));
     48// Because we are using a size_t to store the size in bytes of array buffers, we cannot support 4GB on 32-bit platforms.
     49// So we are sticking with 2GB. It should in theory be possible to support up to (4GB - 1B) if anyone cares.
    4250#define MAX_ARRAY_BUFFER_SIZE 0x7fffffffu
     51#endif
    4352
    4453class VM;
     
    5261class SharedArrayBufferContents : public ThreadSafeRefCounted<SharedArrayBufferContents> {
    5362public:
    54     SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&&);
     63    SharedArrayBufferContents(void* data, size_t, ArrayBufferDestructorFunction&&);
    5564    ~SharedArrayBufferContents();
    5665   
     
    6170    DataType m_data;
    6271    PackedArrayBufferDestructorFunction m_destructor;
    63     unsigned m_sizeInBytes;
     72    size_t m_sizeInBytes;
    6473};
    6574
     
    6877public:
    6978    JS_EXPORT_PRIVATE ArrayBufferContents();
    70     JS_EXPORT_PRIVATE ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&&);
     79    JS_EXPORT_PRIVATE ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&&);
    7180   
    7281    JS_EXPORT_PRIVATE ArrayBufferContents(ArrayBufferContents&&);
     
    8089   
    8190    void* data() const { return m_data.getMayBeNull(sizeInBytes()); }
    82     unsigned sizeInBytes() const { return m_sizeInBytes; }
     91    size_t sizeInBytes() const { return m_sizeInBytes; }
    8392   
    8493    bool isShared() const { return m_shared; }
     
    95104    };
    96105
    97     void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy);
     106    void tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy);
    98107   
    99108    void makeShared();
     
    106115    PackedArrayBufferDestructorFunction m_destructor;
    107116    PackedRefPtr<SharedArrayBufferContents> m_shared;
    108     unsigned m_sizeInBytes;
     117    size_t m_sizeInBytes;
    109118};
    110119
    111120class ArrayBuffer : public GCIncomingRefCounted<ArrayBuffer> {
    112121public:
    113     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
     122    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize);
    114123    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBuffer&);
    115     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, unsigned byteLength);
     124    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, size_t byteLength);
    116125    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBufferContents&&);
    117     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, unsigned byteLength);
    118     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&&);
    119     JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize);
     126    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, size_t byteLength);
     127    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&&);
     128    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize);
    120129    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(ArrayBuffer&);
    121     JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, unsigned byteLength);
     130    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, size_t byteLength);
    122131
    123132    // Only for use by Uint8ClampedArray::tryCreateUninitialized and SharedBuffer::tryCreateArrayBuffer.
    124     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
    125     JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(unsigned numElements, unsigned elementByteSize);
     133    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(size_t numElements, unsigned elementByteSize);
     134    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(size_t numElements, unsigned elementByteSize);
    126135
    127136    inline void* data();
    128137    inline const void* data() const;
    129     inline unsigned byteLength() const;
     138    inline size_t byteLength() const;
    130139   
    131140    void makeShared();
     
    138147    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin, double end) const;
    139148    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin) const;
    140     JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(unsigned begin, unsigned end) const;
     149    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(size_t begin, size_t end) const;
    141150   
    142151    inline void pin();
     
    162171
    163172private:
    164     static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
    165     static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned);
    166     static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
     173    static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
     174    static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, size_t);
     175    static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
    167176    ArrayBuffer(ArrayBufferContents&&);
    168     inline unsigned clampIndex(double index) const;
    169     static inline unsigned clampValue(double x, unsigned left, unsigned right);
     177    inline size_t clampIndex(double index) const;
     178    static inline size_t clampValue(double x, size_t left, size_t right);
    170179
    171180    void notifyDetaching(VM&);
     
    193202}
    194203
    195 unsigned ArrayBuffer::byteLength() const
     204size_t ArrayBuffer::byteLength() const
    196205{
    197206    return m_contents.sizeInBytes();
     
    206215{
    207216    // FIXME: We probably want to scale this by the shared ref count or something.
    208     return sizeof(ArrayBuffer) + static_cast<size_t>(byteLength());
     217    return sizeof(ArrayBuffer) + byteLength();
    209218}
    210219
  • trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2626#include "config.h"
    2727#include "ArrayBufferView.h"
    28 #include <wtf/CheckedArithmetic.h>
    2928
    3029namespace JSC {
    3130
    3231ArrayBufferView::ArrayBufferView(
    33     RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
     32    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
    3433        : m_byteOffset(byteOffset)
    3534        , m_isDetachable(true)
     
    3736        , m_buffer(WTFMove(buffer))
    3837{
    39     Checked<unsigned, CrashOnOverflow> length(byteOffset);
     38    Checked<size_t, CrashOnOverflow> length(byteOffset);
    4039    length += byteLength;
    4140    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(length <= m_buffer->byteLength());
  • trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030#include <algorithm>
    3131#include <limits.h>
     32#include <wtf/CheckedArithmetic.h>
    3233#include <wtf/RefCounted.h>
    3334#include <wtf/RefPtr.h>
     
    7879    void* data() const { return baseAddress(); }
    7980
    80     unsigned byteOffset() const
     81    size_t byteOffset() const
    8182    {
    8283        if (isDetached())
     
    8586    }
    8687
    87     unsigned byteLength() const { return m_byteLength; }
     88    size_t byteLength() const { return m_byteLength; }
    8889
    8990    JS_EXPORT_PRIVATE void setDetachable(bool);
     
    9394
    9495    // Helper to verify byte offset is size aligned.
    95     static bool verifyByteOffsetAlignment(unsigned byteOffset, size_t size)
    96     {
    97         return !(byteOffset & (size - 1));
    98     }
    99 
    100     // Helper to verify that a given sub-range of an ArrayBuffer is
    101     // within range.
    102     static bool verifySubRangeLength(const ArrayBuffer& buffer, unsigned byteOffset, unsigned numElements, size_t size)
    103     {
    104         unsigned byteLength = buffer.byteLength();
     96    static bool verifyByteOffsetAlignment(size_t byteOffset, size_t elementSize)
     97    {
     98        return !(byteOffset & (elementSize - 1));
     99    }
     100
     101    // Helper to verify that a given sub-range of an ArrayBuffer is within range.
     102    static bool verifySubRangeLength(const ArrayBuffer& buffer, size_t byteOffset, size_t numElements, unsigned elementSize)
     103    {
     104        size_t byteLength = buffer.byteLength();
    105105        if (byteOffset > byteLength)
    106106            return false;
    107         unsigned remainingElements = (byteLength - byteOffset) / size;
     107        size_t remainingElements = (byteLength - byteOffset) / static_cast<size_t>(elementSize);
    108108        if (numElements > remainingElements)
    109109            return false;
     
    114114   
    115115protected:
    116     JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned byteLength);
    117 
    118     inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
    119 
    120     inline bool setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset);
    121     inline bool getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset);
    122 
    123     inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength);
    124 
    125     static inline void calculateOffsetAndLength(
    126         int start, int end, unsigned arraySize,
    127         unsigned* offset, unsigned* length);
     116    JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
     117
     118    inline bool setImpl(ArrayBufferView*, size_t byteOffset);
     119
     120    inline bool setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset);
     121    inline bool getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset);
     122
     123    inline bool zeroRangeImpl(size_t byteOffset, size_t rangeByteLength);
    128124
    129125    // Input offset is in number of elements from this array's view;
     
    132128    static void clampOffsetAndNumElements(
    133129        const ArrayBuffer& buffer,
    134         unsigned arrayByteOffset,
    135         unsigned *offset,
    136         unsigned *numElements)
    137     {
    138         unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
     130        size_t arrayByteOffset,
     131        size_t *offset,
     132        size_t *numElements)
     133    {
     134        size_t maxOffset = (std::numeric_limits<size_t>::max() - arrayByteOffset) / sizeof(T);
    139135        if (*offset > maxOffset) {
    140136            *offset = buffer.byteLength();
     
    142138            return;
    143139        }
    144         *offset = arrayByteOffset + *offset * sizeof(T);
    145         *offset = std::min(buffer.byteLength(), *offset);
    146         unsigned remainingElements = (buffer.byteLength() - *offset) / sizeof(T);
     140        CheckedSize adjustedOffset = *offset;
     141        adjustedOffset *= sizeof(T);
     142        adjustedOffset += arrayByteOffset;
     143        if (adjustedOffset.hasOverflowed() || adjustedOffset.value() > buffer.byteLength())
     144            *offset = buffer.byteLength();
     145        else
     146            *offset = adjustedOffset.value();
     147        size_t remainingElements = (buffer.byteLength() - *offset) / sizeof(T);
    147148        *numElements = std::min(remainingElements, *numElements);
    148149    }
    149150
    150     unsigned m_byteOffset : 31;
     151#if USE(LARGE_TYPED_ARRAYS)
     152    uint64_t m_byteOffset : 63;
     153#else
     154    uint32_t m_byteOffset : 31;
     155#endif
    151156    bool m_isDetachable : 1;
    152     unsigned m_byteLength;
     157    UCPURegister m_byteLength;
    153158
    154159    using BaseAddress = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
     
    161166};
    162167
    163 bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset)
    164 {
    165     if (byteOffset > byteLength()
    166         || byteOffset + array->byteLength() > byteLength()
    167         || byteOffset + array->byteLength() < byteOffset) {
    168         // Out of range offset or overflow
    169         return false;
    170     }
    171    
     168bool ArrayBufferView::setImpl(ArrayBufferView* array, size_t byteOffset)
     169{
     170    if (!isSumSmallerThanOrEqual(byteOffset, array->byteLength(), byteLength()))
     171        return false;
     172
    172173    uint8_t* base = static_cast<uint8_t*>(baseAddress());
    173174    memmove(base + byteOffset, array->baseAddress(), array->byteLength());
     
    175176}
    176177
    177 bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset)
    178 {
    179     if (byteOffset > byteLength()
    180         || byteOffset + dataByteLength > byteLength()
    181         || byteOffset + dataByteLength < byteOffset) {
    182         // Out of range offset or overflow
    183         return false;
    184     }
     178bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset)
     179{
     180    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
     181        return false;
    185182
    186183    uint8_t* base = static_cast<uint8_t*>(baseAddress());
     
    189186}
    190187
    191 bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset)
    192 {
    193     if (byteOffset > byteLength()
    194         || byteOffset + dataByteLength > byteLength()
    195         || byteOffset + dataByteLength < byteOffset) {
    196         // Out of range offset or overflow
    197         return false;
    198     }
     188bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset)
     189{
     190    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
     191        return false;
    199192
    200193    const uint8_t* base = static_cast<const uint8_t*>(baseAddress());
     
    203196}
    204197
    205 bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength)
    206 {
    207     if (byteOffset > byteLength()
    208         || byteOffset + rangeByteLength > byteLength()
    209         || byteOffset + rangeByteLength < byteOffset) {
    210         // Out of range offset or overflow
    211         return false;
    212     }
    213    
     198bool ArrayBufferView::zeroRangeImpl(size_t byteOffset, size_t rangeByteLength)
     199{
     200    if (!isSumSmallerThanOrEqual(byteOffset, rangeByteLength, byteLength()))
     201        return false;
     202
    214203    uint8_t* base = static_cast<uint8_t*>(baseAddress());
    215204    memset(base + byteOffset, 0, rangeByteLength);
     
    217206}
    218207
    219 void ArrayBufferView::calculateOffsetAndLength(
    220     int start, int end, unsigned arraySize, unsigned* offset, unsigned* length)
    221 {
    222     if (start < 0)
    223         start += arraySize;
    224     if (start < 0)
    225         start = 0;
    226     if (end < 0)
    227         end += arraySize;
    228     if (end < 0)
    229         end = 0;
    230     if (static_cast<unsigned>(end) > arraySize)
    231         end = arraySize;
    232     if (end < start)
    233         end = start;
    234     *offset = static_cast<unsigned>(start);
    235     *length = static_cast<unsigned>(end - start);
    236 }
    237 
    238208} // namespace JSC
    239209
  • trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp

    r284237 r284330  
    121121        RETURN_IF_EXCEPTION(scope, 0);
    122122    }
    123    
    124     ASSERT(typedArrayView->length() <= static_cast<unsigned>(INT_MAX));
     123
    125124    if (accessIndex >= typedArrayView->length()) {
    126125        throwRangeError(globalObject, scope, "Access index out of bounds for atomic access."_s);
  • trunk/Source/JavaScriptCore/runtime/DataView.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333namespace JSC {
    3434
    35 DataView::DataView(RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
     35DataView::DataView(RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
    3636    : ArrayBufferView(WTFMove(buffer), byteOffset, byteLength)
    3737{
     
    3939
    4040Ref<DataView> DataView::create(
    41     RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
     41    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
    4242{
    4343    return adoptRef(*new DataView(WTFMove(buffer), byteOffset, byteLength));
     
    4646Ref<DataView> DataView::create(RefPtr<ArrayBuffer>&& buffer)
    4747{
    48     unsigned byteLength = buffer->byteLength();
     48    size_t byteLength = buffer->byteLength();
    4949    return create(WTFMove(buffer), 0, byteLength);
    5050}
  • trunk/Source/JavaScriptCore/runtime/DataView.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333class DataView final : public ArrayBufferView {
    3434public:
    35     JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
     35    JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
    3636    static Ref<DataView> create(RefPtr<ArrayBuffer>&&);
    3737   
     
    4444   
    4545    template<typename T>
    46     T get(unsigned offset, bool littleEndian, bool* status = nullptr)
     46    T get(size_t offset, bool littleEndian, bool* status = nullptr)
    4747    {
    4848        if (status) {
     
    6060   
    6161    template<typename T>
    62     T read(unsigned& offset, bool littleEndian, bool* status = nullptr)
     62    T read(size_t& offset, bool littleEndian, bool* status = nullptr)
    6363    {
    6464        T result = this->template get<T>(offset, littleEndian, status);
     
    6969   
    7070    template<typename T>
    71     void set(unsigned offset, T value, bool littleEndian, bool* status = nullptr)
     71    void set(size_t offset, T value, bool littleEndian, bool* status = nullptr)
    7272    {
    7373        if (status) {
     
    8484
    8585private:
    86     DataView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned byteLength);
     86    DataView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
    8787};
    8888
  • trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3434class GenericTypedArrayView final : public ArrayBufferView {
    3535public:
    36     static Ref<GenericTypedArrayView> create(unsigned length);
    37     static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, unsigned length);
    38     static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
    39     static RefPtr<GenericTypedArrayView> tryCreate(unsigned length);
    40     static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, unsigned length);
    41     static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
     36    static Ref<GenericTypedArrayView> create(size_t length);
     37    static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, size_t length);
     38    static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
     39    static RefPtr<GenericTypedArrayView> tryCreate(size_t length);
     40    static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, size_t length);
     41    static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
    4242   
    43     static Ref<GenericTypedArrayView> createUninitialized(unsigned length);
    44     static RefPtr<GenericTypedArrayView> tryCreateUninitialized(unsigned length);
     43    static Ref<GenericTypedArrayView> createUninitialized(size_t length);
     44    static RefPtr<GenericTypedArrayView> tryCreateUninitialized(size_t length);
    4545   
    4646    typename Adaptor::Type* data() const { return static_cast<typename Adaptor::Type*>(baseAddress()); }
    4747   
    48     bool set(GenericTypedArrayView<Adaptor>* array, unsigned offset)
     48    bool set(GenericTypedArrayView<Adaptor>* array, size_t offset)
    4949    {
    5050        return setImpl(array, offset * sizeof(typename Adaptor::Type));
    5151    }
    5252   
    53     bool setRange(const typename Adaptor::Type* data, size_t count, unsigned offset)
     53    bool setRange(const typename Adaptor::Type* data, size_t count, size_t offset)
    5454    {
    5555        return setRangeImpl(
     
    5959    }
    6060   
    61     bool zeroRange(unsigned offset, size_t count)
     61    bool zeroRange(size_t offset, size_t count)
    6262    {
    6363        return zeroRangeImpl(offset * sizeof(typename Adaptor::Type), count * sizeof(typename Adaptor::Type));
     
    6666    void zeroFill() { zeroRange(0, length()); }
    6767   
    68     unsigned length() const
     68    size_t length() const
    6969    {
    7070        if (isDetached())
     
    7373    }
    7474
    75     typename Adaptor::Type item(unsigned index) const
     75    typename Adaptor::Type item(size_t index) const
    7676    {
    7777        ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
     
    7979    }
    8080   
    81     void set(unsigned index, double value) const
     81    void set(size_t index, double value) const
    8282    {
    8383        ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
     
    8585    }
    8686
    87     void setNative(unsigned index, typename Adaptor::Type value) const
     87    void setNative(size_t index, typename Adaptor::Type value) const
    8888    {
    8989        ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
     
    9191    }
    9292
    93     bool getRange(typename Adaptor::Type* data, size_t count, unsigned offset)
     93    bool getRange(typename Adaptor::Type* data, size_t count, size_t offset)
    9494    {
    9595        return getRangeImpl(
     
    9999    }
    100100
    101     bool checkInboundData(unsigned offset, size_t count) const
     101    bool checkInboundData(size_t offset, size_t count) const
    102102    {
    103         unsigned length = this->length();
    104         return (offset <= length
    105             && offset + count <= length
    106             // check overflow
    107             && offset + count >= offset);
     103        return isSumSmallerThanOrEqual(offset, count, this->length());
    108104    }
    109    
    110     RefPtr<GenericTypedArrayView> subarray(int start) const;
    111     RefPtr<GenericTypedArrayView> subarray(int start, int end) const;
    112105   
    113106    TypedArrayType getType() const final
     
    119112
    120113private:
    121     GenericTypedArrayView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
     114    GenericTypedArrayView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
    122115};
    123116
  • trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333template<typename Adaptor>
    3434GenericTypedArrayView<Adaptor>::GenericTypedArrayView(
    35 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
     35RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
    3636    : ArrayBufferView(WTFMove(buffer), byteOffset, length * sizeof(typename Adaptor::Type))
    3737{
     38    ASSERT((length / sizeof(typename Adaptor::Type)) < std::numeric_limits<size_t>::max());
    3839}
    3940
    4041template<typename Adaptor>
    41 Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(unsigned length)
     42Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(size_t length)
    4243{
    4344    auto result = tryCreate(length);
     
    4849template<typename Adaptor>
    4950Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
    50     const typename Adaptor::Type* array, unsigned length)
     51    const typename Adaptor::Type* array, size_t length)
    5152{
    5253    auto result = tryCreate(array, length);
     
    5758template<typename Adaptor>
    5859Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
    59     RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
     60    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
    6061{
    6162    auto result = tryCreate(WTFMove(buffer), byteOffset, length);
     
    6566
    6667template<typename Adaptor>
    67 RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(unsigned length)
     68RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(size_t length)
    6869{
    6970    auto buffer = ArrayBuffer::tryCreate(length, sizeof(typename Adaptor::Type));
     
    7576template<typename Adaptor>
    7677RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
    77     const typename Adaptor::Type* array, unsigned length)
     78    const typename Adaptor::Type* array, size_t length)
    7879{
    7980    RefPtr<GenericTypedArrayView> result = tryCreate(length);
     
    8687template<typename Adaptor>
    8788RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
    88     RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
     89    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
    8990{
    9091    if (!buffer)
     
    101102template<typename Adaptor>
    102103Ref<GenericTypedArrayView<Adaptor>>
    103 GenericTypedArrayView<Adaptor>::createUninitialized(unsigned length)
     104GenericTypedArrayView<Adaptor>::createUninitialized(size_t length)
    104105{
    105106    auto result = tryCreateUninitialized(length);
     
    110111template<typename Adaptor>
    111112RefPtr<GenericTypedArrayView<Adaptor>>
    112 GenericTypedArrayView<Adaptor>::tryCreateUninitialized(unsigned length)
     113GenericTypedArrayView<Adaptor>::tryCreateUninitialized(size_t length)
    113114{
    114115    RefPtr<ArrayBuffer> buffer =
     
    117118        return nullptr;
    118119    return tryCreate(WTFMove(buffer), 0, length);
    119 }
    120 
    121 template<typename Adaptor>
    122 RefPtr<GenericTypedArrayView<Adaptor>>
    123 GenericTypedArrayView<Adaptor>::subarray(int start) const
    124 {
    125     return subarray(start, length());
    126 }
    127 
    128 template<typename Adaptor>
    129 RefPtr<GenericTypedArrayView<Adaptor>>
    130 GenericTypedArrayView<Adaptor>::subarray(int start, int end) const
    131 {
    132     unsigned offset, length;
    133     calculateOffsetAndLength(start, end, this->length(), &offset, &length);
    134     ArrayBuffer* buffer = possiblySharedBuffer();
    135     ASSERT(buffer);
    136     clampOffsetAndNumElements<Adaptor::Type>(*buffer, byteOffset(), &offset, &length);
    137     return tryCreate(buffer, offset, length);
    138120}
    139121
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp

    r284237 r284330  
    4242
    4343JSArrayBufferView::ConstructionContext::ConstructionContext(
    44     Structure* structure, uint32_t length, void* vector)
     44    Structure* structure, size_t length, void* vector)
    4545    : m_structure(structure)
    4646    , m_vector(vector, length)
     
    5555
    5656JSArrayBufferView::ConstructionContext::ConstructionContext(
    57     VM& vm, Structure* structure, uint32_t length, uint32_t elementSize,
     57    VM& vm, Structure* structure, size_t length, unsigned elementSize,
    5858    InitializationMode mode)
    5959    : m_structure(nullptr)
     
    8282    }
    8383
    84     // Don't allow a typed array to use more than 2GB.
    85     if (length > static_cast<unsigned>(INT_MAX) / elementSize)
    86         return;
    87    
    88     size_t size = static_cast<size_t>(length) * static_cast<size_t>(elementSize);
    89     m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size), length);
     84    CheckedSize size = length;
     85    size *= elementSize;
     86    if (size.hasOverflowed() || size > MAX_ARRAY_BUFFER_SIZE)
     87        return;
     88
     89    m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size.value()), length);
    9090    if (!m_vector)
    9191        return;
     
    9393        memset(vector(), 0, size);
    9494   
    95     vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize);
     95    vm.heap.reportExtraMemoryAllocated(size.value());
    9696   
    9797    m_structure = structure;
     
    101101JSArrayBufferView::ConstructionContext::ConstructionContext(
    102102    VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
    103     unsigned byteOffset, unsigned length)
     103    size_t byteOffset, size_t length)
    104104    : m_structure(structure)
    105105    , m_length(length)
     
    115115JSArrayBufferView::ConstructionContext::ConstructionContext(
    116116    Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
    117     unsigned byteOffset, unsigned length, DataViewTag)
     117    size_t byteOffset, size_t length, DataViewTag)
    118118    : m_structure(structure)
    119119    , m_length(length)
     
    239239}
    240240
    241 unsigned JSArrayBufferView::byteLength() const
    242 {
     241size_t JSArrayBufferView::byteLength() const
     242{
     243#if ASSERT_ENABLED
     244    Checked<size_t> result = length();
     245    result *= elementSize(type());
     246    return result.value();
     247#else
     248    // The absence of overflow is already checked in the constructor, so I only add the extra sanity check when asserts are enabled.
    243249    return length() * elementSize(type());
     250#endif
    244251}
    245252
     
    268275
    269276    RefPtr<ArrayBuffer> buffer;
    270     unsigned byteLength = this->byteLength();
     277    size_t byteLength = this->byteLength();
    271278
    272279    switch (m_mode) {
     
    316323    if (!buffer)
    317324        return nullptr;
    318     unsigned byteOffset = this->byteOffset();
    319     unsigned length = this->length();
     325    size_t byteOffset = this->byteOffset();
     326    size_t length = this->length();
    320327    switch (type()) {
    321328#define FACTORY(type) \
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h

    r284237 r284330  
    109109    }
    110110
    111     static constexpr unsigned fastSizeLimit = 1000;
     111    static constexpr size_t fastSizeLimit = 1000;
    112112    using VectorPtr = CagedBarrierPtr<Gigacage::Primitive, void, tagCagedPtr>;
    113113
     
    118118    }
    119119   
    120     static size_t sizeOf(uint32_t length, uint32_t elementSize)
    121     {
    122         return (static_cast<size_t>(length) * elementSize + sizeof(EncodedJSValue) - 1)
    123             & ~(sizeof(EncodedJSValue) - 1);
     120    static size_t sizeOf(size_t length, unsigned elementSize)
     121    {
     122        Checked<size_t> result = length;
     123        result *= elementSize;
     124        result += sizeof(EncodedJSValue) - 1;
     125        return result.value() & ~(sizeof(EncodedJSValue) - 1);
    124126    }
    125127
     
    137139        enum InitializationMode { ZeroFill, DontInitialize };
    138140       
    139         JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, uint32_t length, uint32_t elementSize, InitializationMode = ZeroFill);
     141        JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, size_t length, unsigned elementSize, InitializationMode = ZeroFill);
    140142       
    141143        // This is only for constructing fast typed arrays. It's used by the JIT's slow path.
    142         ConstructionContext(Structure*, uint32_t length, void* vector);
     144        ConstructionContext(Structure*, size_t length, void* vector);
    143145       
    144146        JS_EXPORT_PRIVATE ConstructionContext(
    145147            VM&, Structure*, RefPtr<ArrayBuffer>&&,
    146             unsigned byteOffset, unsigned length);
     148            size_t byteOffset, size_t length);
    147149       
    148150        enum DataViewTag { DataView };
    149151        ConstructionContext(
    150152            Structure*, RefPtr<ArrayBuffer>&&,
    151             unsigned byteOffset, unsigned length, DataViewTag);
     153            size_t byteOffset, size_t length, DataViewTag);
    152154       
    153155        bool operator!() const { return !m_structure; }
     
    155157        Structure* structure() const { return m_structure; }
    156158        void* vector() const { return m_vector.getMayBeNull(m_length); }
    157         uint32_t length() const { return m_length; }
     159        size_t length() const { return m_length; }
    158160        TypedArrayMode mode() const { return m_mode; }
    159161        Butterfly* butterfly() const { return m_butterfly; }
     
    163165        using VectorType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
    164166        VectorType m_vector;
    165         uint32_t m_length;
     167        size_t m_length;
    166168        TypedArrayMode m_mode;
    167169        Butterfly* m_butterfly;
     
    191193    void* vectorWithoutPACValidation() const { return m_vector.getUnsafe(); }
    192194   
    193     inline unsigned byteOffset();
    194     inline std::optional<unsigned> byteOffsetConcurrently();
    195 
    196     unsigned length() const { return m_length; }
    197     unsigned byteLength() const;
     195    inline size_t byteOffset();
     196    inline std::optional<size_t> byteOffsetConcurrently();
     197
     198    size_t length() const { return m_length; }
     199    size_t byteLength() const;
    198200
    199201    DECLARE_EXPORT_INFO;
     
    220222
    221223    VectorPtr m_vector;
    222     uint32_t m_length;
     224    size_t m_length;
    223225    TypedArrayMode m_mode;
    224226};
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h

    r284237 r284330  
    100100        bitwise_cast<uint8_t*>(vectorWithoutPACValidation()) - static_cast<uint8_t*>(buffer->data());
    101101
    102     unsigned result = static_cast<unsigned>(delta);
     102    size_t result = static_cast<size_t>(delta);
    103103    if (requester == Mutator)
    104104        ASSERT(static_cast<ptrdiff_t>(result) == delta);
     
    111111}
    112112
    113 inline unsigned JSArrayBufferView::byteOffset()
     113inline size_t JSArrayBufferView::byteOffset()
    114114{
    115     return byteOffsetImpl<Mutator, unsigned>();
     115    return byteOffsetImpl<Mutator, size_t>();
    116116}
    117117
    118 inline std::optional<unsigned> JSArrayBufferView::byteOffsetConcurrently()
     118inline std::optional<size_t> JSArrayBufferView::byteOffsetConcurrently()
    119119{
    120     return byteOffsetImpl<ConcurrentThread, std::optional<unsigned>>();
     120    return byteOffsetImpl<ConcurrentThread, std::optional<size_t>>();
    121121}
    122122
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.h

    r284237 r284330  
    3838#include <wtf/MediaTime.h>
    3939#include <wtf/Nonmovable.h>
     40#include <wtf/StdIntExtras.h>
    4041#include <wtf/StdLibExtras.h>
    4142#include <wtf/TriState.h>
     
    299300    uint32_t toUInt32(JSGlobalObject*) const;
    300301    uint32_t toIndex(JSGlobalObject*, const char* errorName) const;
     302    size_t toTypedArrayIndex(JSGlobalObject*, const char* errorName) const;
    301303    double toLength(JSGlobalObject*) const;
    302304
  • trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h

    r284237 r284330  
    7070        return 0;
    7171    }
    72     if (d > std::numeric_limits<unsigned>::max()) {
     72
     73    if (isInt32())
     74        return asInt32();
     75
     76    if (d > static_cast<double>(std::numeric_limits<unsigned>::max())) {
    7377        throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large")));
    7478        return 0;
    7579    }
    7680
     81    RELEASE_AND_RETURN(scope, JSC::toInt32(d));
     82}
     83
     84inline size_t JSValue::toTypedArrayIndex(JSGlobalObject* globalObject, const char* errorName) const
     85{
     86    VM& vm = getVM(globalObject);
     87    auto scope = DECLARE_THROW_SCOPE(vm);
     88
     89    double d = toNumber(globalObject);
     90    RETURN_IF_EXCEPTION(scope, 0);
     91    if (d <= -1) {
     92        throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " cannot be negative")));
     93        return 0;
     94    }
     95
    7796    if (isInt32())
    7897        return asInt32();
    79     RELEASE_AND_RETURN(scope, JSC::toInt32(d));
     98
     99    if (d > static_cast<double>(MAX_ARRAY_BUFFER_SIZE)) {
     100        throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large")));
     101        return 0;
     102    }
     103
     104    // All of this monstrosity is just to give the correct result on 1<<32.
     105    size_t outputOffset = 0;
     106    double inputOffset = 0;
     107    size_t int32Max = std::numeric_limits<int32_t>::max();
     108    if (d > static_cast<double>(int32Max)) {
     109        outputOffset = int32Max;
     110        inputOffset = int32Max;
     111    }
     112    RELEASE_AND_RETURN(scope, outputOffset + static_cast<size_t>(static_cast<uint32_t>(JSC::toInt32(d - inputOffset))));
    80113}
    81114
  • trunk/Source/JavaScriptCore/runtime/JSDataView.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4343JSDataView* JSDataView::create(
    4444    JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
    45     unsigned byteOffset, unsigned byteLength)
     45    size_t byteOffset, size_t byteLength)
    4646{
    4747    VM& vm = globalObject->vm();
     
    7171}
    7272
    73 JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, unsigned)
     73JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, size_t)
    7474{
    7575    UNREACHABLE_FOR_PLATFORM();
     
    7777}
    7878
    79 JSDataView* JSDataView::create(JSGlobalObject*, Structure*, unsigned)
     79JSDataView* JSDataView::create(JSGlobalObject*, Structure*, size_t)
    8080{
    8181    UNREACHABLE_FOR_PLATFORM();
     
    8383}
    8484
    85 bool JSDataView::set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsigned)
     85bool JSDataView::set(JSGlobalObject*, size_t, JSObject*, size_t, size_t)
    8686{
    8787    UNREACHABLE_FOR_PLATFORM();
     
    8989}
    9090
    91 bool JSDataView::setIndex(JSGlobalObject*, unsigned, JSValue)
     91bool JSDataView::setIndex(JSGlobalObject*, size_t, JSValue)
    9292{
    9393    UNREACHABLE_FOR_PLATFORM();
  • trunk/Source/JavaScriptCore/runtime/JSDataView.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4747
    4848    JS_EXPORT_PRIVATE static JSDataView* create(
    49         JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset,
    50         unsigned byteLength);
     49        JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
    5150   
    5251    // Dummy methods, which don't actually work; these are just in place to
    5352    // placate some template specialization we do elsewhere.
    54     static JSDataView* createUninitialized(JSGlobalObject*, Structure*, unsigned length);
    55     static JSDataView* create(JSGlobalObject*, Structure*, unsigned length);
    56     bool set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsigned length);
    57     bool setIndex(JSGlobalObject*, unsigned, JSValue);
     53    static JSDataView* createUninitialized(JSGlobalObject*, Structure*, size_t length);
     54    static JSDataView* create(JSGlobalObject*, Structure*, size_t length);
     55    bool set(JSGlobalObject*, size_t, JSObject*, size_t, size_t length);
     56    bool setIndex(JSGlobalObject*, size_t, JSValue);
    5857   
    5958    ArrayBuffer* possiblySharedBuffer() const { return m_buffer; }
  • trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp

    r284237 r284330  
    11/*
    2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    137137        return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s);
    138138   
    139     unsigned byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
     139    size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
    140140    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    141141   
    142142    bool littleEndian = false;
    143     unsigned elementSize = sizeof(typename Adaptor::Type);
     143    size_t elementSize = sizeof(typename Adaptor::Type);
    144144    if (elementSize > 1 && callFrame->argumentCount() >= 2) {
    145145        littleEndian = callFrame->uncheckedArgument(1).toBoolean(globalObject);
     
    150150        return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
    151151
    152     unsigned byteLength = dataView->length();
     152    size_t byteLength = dataView->length();
    153153    if (elementSize > byteLength || byteOffset > byteLength - elementSize)
    154154        return throwVMRangeError(globalObject, scope, "Out of bounds access"_s);
     
    183183        return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s);
    184184   
    185     unsigned byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
     185    size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
    186186    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    187187
     
    196196   
    197197    bool littleEndian = false;
    198     unsigned elementSize = sizeof(typename Adaptor::Type);
     198    size_t elementSize = sizeof(typename Adaptor::Type);
    199199    if (elementSize > 1 && callFrame->argumentCount() >= 3) {
    200200        littleEndian = callFrame->uncheckedArgument(2).toBoolean(globalObject);
     
    205205        return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
    206206
    207     unsigned byteLength = dataView->length();
     207    size_t byteLength = dataView->length();
    208208    if (elementSize > byteLength || byteOffset > byteLength - elementSize)
    209209        return throwVMRangeError(globalObject, scope, "Out of bounds access"_s);
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h

    r284237 r284330  
    2929#include "ThrowScope.h"
    3030#include "ToNativeFromValue.h"
     31#include <wtf/CheckedArithmetic.h>
    3132
    3233namespace JSC {
     
    5657//     Butterfly* B     // from JSObject
    5758//     ElementType* V
    58 //     uint32_t L
     59//     size_t L
    5960//     TypedArrayMode M
    6061//
    61 // These fields take up a total of four pointer-width words. FIXME: Make
     62// These fields take up a total of five pointer-width words. FIXME: Make
    6263// it take less words!
    6364//
     
    104105    static constexpr unsigned elementSize = sizeof(typename Adaptor::Type);
    105106
    106     static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, unsigned length);
    107     static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, unsigned length, void* vector);
    108     static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, unsigned length);
    109     static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
     107    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, size_t length);
     108    static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, size_t length, void* vector);
     109    static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, size_t length);
     110    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
    110111    static JSGenericTypedArrayView* create(VM&, Structure*, RefPtr<typename Adaptor::ViewType>&& impl);
    111112    static JSGenericTypedArrayView* create(Structure*, JSGlobalObject*, RefPtr<typename Adaptor::ViewType>&& impl);
    112113   
    113     unsigned byteLength() const { return m_length * sizeof(typename Adaptor::Type); }
     114    size_t byteLength() const { return m_length * sizeof(typename Adaptor::Type); }
    114115    size_t byteSize() const { return sizeOf(m_length, sizeof(typename Adaptor::Type)); }
    115116   
     
    123124    }
    124125
    125     bool inBounds(unsigned i) const
     126    bool inBounds(size_t i) const
    126127    {
    127128        return i < m_length;
     
    130131    // These methods are meant to match indexed access methods that JSObject
    131132    // supports - hence the slight redundancy.
    132     bool canGetIndexQuickly(unsigned i) const
     133    bool canGetIndexQuickly(size_t i) const
    133134    {
    134135        return inBounds(i) && Adaptor::canConvertToJSQuickly;
    135136    }
    136     bool canSetIndexQuickly(unsigned i, JSValue value) const
     137    bool canSetIndexQuickly(size_t i, JSValue value) const
    137138    {
    138139        return i < m_length && value.isNumber() && Adaptor::canConvertToJSQuickly;
    139140    }
    140141   
    141     typename Adaptor::Type getIndexQuicklyAsNativeValue(unsigned i) const
     142    typename Adaptor::Type getIndexQuicklyAsNativeValue(size_t i) const
    142143    {
    143144        ASSERT(i < m_length);
     
    145146    }
    146147   
    147     JSValue getIndexQuickly(unsigned i) const
     148    JSValue getIndexQuickly(size_t i) const
    148149    {
    149150        return Adaptor::toJSValue(nullptr, getIndexQuicklyAsNativeValue(i));
    150151    }
    151152   
    152     void setIndexQuicklyToNativeValue(unsigned i, typename Adaptor::Type value)
     153    void setIndexQuicklyToNativeValue(size_t i, typename Adaptor::Type value)
    153154    {
    154155        ASSERT(i < m_length);
     
    156157    }
    157158   
    158     void setIndexQuickly(unsigned i, JSValue value)
     159    void setIndexQuickly(size_t i, JSValue value)
    159160    {
    160161        ASSERT(!value.isObject());
     
    162163    }
    163164   
    164     bool setIndex(JSGlobalObject* globalObject, unsigned i, JSValue jsValue)
     165    bool setIndex(JSGlobalObject* globalObject, size_t i, JSValue jsValue)
    165166    {
    166167        VM& vm = getVM(globalObject);
     
    177178    }
    178179
    179     static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) { return toNativeFromValue<Adaptor>(globalObject, jsValue); }
    180 
    181     static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) { return toNativeFromValueWithoutCoercion<Adaptor>(jsValue); }
     180    static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue)
     181    {
     182        return toNativeFromValue<Adaptor>(globalObject, jsValue);
     183    }
     184
     185    static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue)
     186    {
     187        return toNativeFromValueWithoutCoercion<Adaptor>(jsValue);
     188    }
    182189
    183190    void sort()
     
    199206    }
    200207
    201     bool canAccessRangeQuickly(unsigned offset, unsigned length)
    202     {
    203         return offset <= m_length
    204             && offset + length <= m_length
    205             // check overflow
    206             && offset + length >= offset;
     208    bool canAccessRangeQuickly(size_t offset, size_t length)
     209    {
     210        return isSumSmallerThanOrEqual(offset, length, m_length);
    207211    }
    208212   
    209213    // Like canSetQuickly, except: if it returns false, it will throw the
    210214    // appropriate exception.
    211     bool validateRange(JSGlobalObject*, unsigned offset, unsigned length);
     215    bool validateRange(JSGlobalObject*, size_t offset, size_t length);
    212216
    213217    // Returns true if successful, and false on error; if it returns false
    214218    // then it will have thrown an exception.
    215     bool set(JSGlobalObject*, unsigned offset, JSObject*, unsigned objectOffset, unsigned length, CopyType type = CopyType::Unobservable);
     219    bool set(JSGlobalObject*, size_t offset, JSObject*, size_t objectOffset, size_t length, CopyType = CopyType::Unobservable);
    216220   
    217221    RefPtr<typename Adaptor::ViewType> possiblySharedTypedImpl();
     
    319323    template<typename OtherAdaptor>
    320324    bool setWithSpecificType(
    321         JSGlobalObject*, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>*,
    322         unsigned objectOffset, unsigned length, CopyType);
     325        JSGlobalObject*, size_t offset, JSGenericTypedArrayView<OtherAdaptor>*,
     326        size_t objectOffset, size_t length, CopyType);
    323327
    324328    // The ECMA 6 spec states that floating point Typed Arrays should have the following ordering:
     
    350354    {
    351355        ElementType* array = typedVector();
    352         for (unsigned i = 0; i < m_length; i++)
     356        for (size_t i = 0; i < m_length; i++)
    353357            array[i] = purifyNaN(array[i]);
    354358    }
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h

    r284237 r284330  
    144144
    145145template<typename ViewClass>
    146 inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, unsigned offset, std::optional<unsigned> lengthOpt)
     146inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, size_t offset, std::optional<size_t> lengthOpt)
    147147{
    148148    VM& vm = globalObject->vm();
     
    158158        }
    159159
    160         unsigned length = 0;
     160        size_t length = 0;
    161161        if (lengthOpt)
    162162            length = lengthOpt.value();
     
    183183
    184184    if (JSObject* object = jsDynamicCast<JSObject*>(vm, firstValue)) {
    185         unsigned length;
     185        size_t length;
    186186        JSArrayBuffer* customBuffer = nullptr;
    187187
     
    251251    }
    252252
    253     unsigned length = firstValue.toIndex(globalObject, "length");
     253    size_t length = firstValue.toTypedArrayIndex(globalObject, "length");
    254254    RETURN_IF_EXCEPTION(scope, nullptr);
    255255    RELEASE_AND_RETURN(scope, ViewClass::create(globalObject, structure, length));
     
    276276
    277277    JSValue firstValue = callFrame->uncheckedArgument(0);
    278     unsigned offset = 0;
    279     std::optional<unsigned> length = std::nullopt;
     278    size_t offset = 0;
     279    std::optional<size_t> length = std::nullopt;
    280280    if (jsDynamicCast<JSArrayBuffer*>(vm, firstValue) && argCount > 1) {
    281281        offset = callFrame->uncheckedArgument(1).toIndex(globalObject, "byteOffset");
     
    286286            JSValue lengthValue = callFrame->uncheckedArgument(2);
    287287            if (!lengthValue.isUndefined()) {
    288                 length = lengthValue.toIndex(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length");
     288                length = lengthValue.toTypedArrayIndex(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length");
    289289                RETURN_IF_EXCEPTION(scope, encodedJSValue());
    290290            }
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h

    r284237 r284330  
    3535#include "TypeError.h"
    3636#include "TypedArrays.h"
     37#include <wtf/CheckedArithmetic.h>
    3738#include <wtf/text/StringConcatenateNumbers.h>
    3839
     
    4849template<typename Adaptor>
    4950JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
    50     JSGlobalObject* globalObject, Structure* structure, unsigned length)
     51    JSGlobalObject* globalObject, Structure* structure, size_t length)
    5152{
    5253    VM& vm = globalObject->vm();
     
    6667template<typename Adaptor>
    6768JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createWithFastVector(
    68     JSGlobalObject* globalObject, Structure* structure, unsigned length, void* vector)
     69    JSGlobalObject* globalObject, Structure* structure, size_t length, void* vector)
    6970{
    7071    VM& vm = globalObject->vm();
     
    7980
    8081template<typename Adaptor>
    81 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, unsigned length)
     82JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, size_t length)
    8283{
    8384    VM& vm = globalObject->vm();
     
    100101JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
    101102    JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
    102     unsigned byteOffset, unsigned length)
    103 {
    104     VM& vm = globalObject->vm();
    105     auto scope = DECLARE_THROW_SCOPE(vm);
    106     size_t size = sizeof(typename Adaptor::Type);
     103    size_t byteOffset, size_t length)
     104{
     105    VM& vm = globalObject->vm();
     106    auto scope = DECLARE_THROW_SCOPE(vm);
     107    size_t elementSize = sizeof(typename Adaptor::Type);
    107108    ASSERT(buffer);
    108     if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, size)) {
     109    if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, elementSize)) {
    109110        throwException(globalObject, scope, createRangeError(globalObject, "Length out of range of buffer"));
    110111        return nullptr;
    111112    }
    112     if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, size)) {
     113    if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, elementSize)) {
    113114        throwException(globalObject, scope, createRangeError(globalObject, "Byte offset is not aligned"));
    114115        return nullptr;
     
    146147template<typename Adaptor>
    147148bool JSGenericTypedArrayView<Adaptor>::validateRange(
    148     JSGlobalObject* globalObject, unsigned offset, unsigned length)
     149    JSGlobalObject* globalObject, size_t offset, size_t length)
    149150{
    150151    VM& vm = globalObject->vm();
     
    160161template<typename OtherAdaptor>
    161162bool JSGenericTypedArrayView<Adaptor>::setWithSpecificType(
    162     JSGlobalObject* globalObject, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>* other,
    163     unsigned otherOffset, unsigned length, CopyType type)
     163    JSGlobalObject* globalObject, size_t offset, JSGenericTypedArrayView<OtherAdaptor>* other,
     164    size_t otherOffset, size_t length, CopyType type)
    164165{
    165166    VM& vm = globalObject->vm();
     
    219220        || (elementSize == otherElementSize && vector() <= other->vector())
    220221        || type == CopyType::LeftToRight) {
    221         for (unsigned i = 0; i < length; ++i) {
     222        for (size_t i = 0; i < length; ++i) {
    222223            setIndexQuicklyToNativeValue(
    223224                offset + i, OtherAdaptor::template convertTo<Adaptor>(
     
    229230    // Now we either have (2B) or (3) - so first we try to cover (2B).
    230231    if (elementSize == otherElementSize) {
    231         for (unsigned i = length; i--;) {
     232        for (size_t i = length; i--;) {
    232233            setIndexQuicklyToNativeValue(
    233234                offset + i, OtherAdaptor::template convertTo<Adaptor>(
     
    239240    // Fail: we need an intermediate transfer buffer (i.e. case (3)).
    240241    Vector<typename Adaptor::Type, 32> transferBuffer(length);
    241     for (unsigned i = length; i--;) {
     242    for (size_t i = length; i--;) {
    242243        transferBuffer[i] = OtherAdaptor::template convertTo<Adaptor>(
    243244            other->getIndexQuicklyAsNativeValue(i + otherOffset));
    244245    }
    245     for (unsigned i = length; i--;)
     246    for (size_t i = length; i--;)
    246247        setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]);
    247248   
     
    251252template<typename Adaptor>
    252253bool JSGenericTypedArrayView<Adaptor>::set(
    253     JSGlobalObject* globalObject, unsigned offset, JSObject* object, unsigned objectOffset, unsigned length, CopyType type)
     254    JSGlobalObject* globalObject, size_t offset, JSObject* object, size_t objectOffset, size_t length, CopyType type)
    254255{
    255256    VM& vm = globalObject->vm();
     
    258259    const ClassInfo* ci = object->classInfo(vm);
    259260    if (ci->typedArrayStorageType == Adaptor::typeValue) {
    260         // The super fast case: we can just memcpy since we're the same type.
     261        // The super fast case: we can just memmove since we're the same type.
    261262        JSGenericTypedArrayView* other = jsCast<JSGenericTypedArrayView*>(object);
    262263        length = std::min(length, other->length());
     
    313314            return false;
    314315
     316        // Verify that we won't ever call object->get() with an index of UINT_MAX or more
     317        RELEASE_ASSERT(isSumSmallerThanOrEqual(static_cast<uint64_t>(length), static_cast<uint64_t>(objectOffset), static_cast<uint64_t>(std::numeric_limits<unsigned>::max())));
    315318        // We could optimize this case. But right now, we don't.
    316         for (unsigned i = 0; i < length; ++i) {
    317             JSValue value = object->get(globalObject, i + objectOffset);
     319        for (size_t i = 0; i < length; ++i) {
     320            JSValue value = object->get(globalObject, static_cast<unsigned>(i + objectOffset));
    318321            RETURN_IF_EXCEPTION(scope, false);
    319322            bool success = setIndex(globalObject, offset + i, value);
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r284237 r284330  
    6161}
    6262
     63class ArrayProfile;
    6364class Exception;
    6465class GetterSetter;
     
    212213    {
    213214        VM& vm = getVM(globalObject);
    214         if (canSetIndexQuickly(propertyName, value)) {
    215             setIndexQuickly(vm, propertyName, value);
     215        if (trySetIndexQuickly(vm, propertyName, value))
    216216            return true;
    217         }
    218217        return methodTable(vm)->putByIndex(this, globalObject, propertyName, value, shouldThrow);
    219218    }
     
    290289
    291290    bool canGetIndexQuicklyForTypedArray(unsigned) const;
    292     JSValue getIndexQuicklyForTypedArray(unsigned) const;
     291    JSValue getIndexQuicklyForTypedArray(unsigned, ArrayProfile* = nullptr) const;
    293292   
    294293    bool canGetIndexQuickly(unsigned i) const
     
    346345        }
    347346    }
    348        
    349     JSValue tryGetIndexQuickly(unsigned i) const
     347
     348    // Uses the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant
     349    JSValue tryGetIndexQuickly(unsigned i, ArrayProfile* arrayProfile = nullptr) const
    350350    {
    351351        const Butterfly* butterfly = this->butterfly();
     
    353353        case ALL_BLANK_INDEXING_TYPES:
    354354            if (canGetIndexQuicklyForTypedArray(i))
    355                 return getIndexQuicklyForTypedArray(i);
     355                return getIndexQuicklyForTypedArray(i, arrayProfile);
    356356            break;
    357357        case ALL_UNDECIDED_INDEXING_TYPES:
     
    412412    }
    413413
    414     bool canSetIndexQuicklyForTypedArray(unsigned, JSValue) const;
    415414    void setIndexQuicklyForTypedArray(unsigned, JSValue);
    416        
    417     bool canSetIndexQuickly(unsigned i, JSValue value)
     415    void setIndexQuicklyForArrayStorageIndexingType(VM&, unsigned, JSValue);
     416
     417    // Return true to indicate success
     418    // Use the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant
     419    bool trySetIndexQuicklyForTypedArray(unsigned, JSValue, ArrayProfile*);
     420    bool trySetIndexQuickly(VM& vm, unsigned i, JSValue v, ArrayProfile* arrayProfile = nullptr)
    418421    {
    419422        Butterfly* butterfly = this->butterfly();
    420423        switch (indexingMode()) {
    421424        case ALL_BLANK_INDEXING_TYPES:
    422             return canSetIndexQuicklyForTypedArray(i, value);
     425            return trySetIndexQuicklyForTypedArray(i, v, arrayProfile);
    423426        case ALL_UNDECIDED_INDEXING_TYPES:
    424427            return false;
    425         case ALL_WRITABLE_INT32_INDEXING_TYPES:
    426         case ALL_WRITABLE_DOUBLE_INDEXING_TYPES:
    427         case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES:
     428        case ALL_WRITABLE_INT32_INDEXING_TYPES: {
     429            if (i >= butterfly->vectorLength())
     430                return false;
     431            if (!v.isInt32()) {
     432                convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v);
     433                return true;
     434            }
     435            FALLTHROUGH;
     436        }
     437        case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES: {
     438            if (i >= butterfly->vectorLength())
     439                return false;
     440            butterfly->contiguous().at(this, i).setWithoutWriteBarrier(v);
     441            if (i >= butterfly->publicLength())
     442                butterfly->setPublicLength(i + 1);
     443            vm.heap.writeBarrier(this, v);
     444            return true;
     445        }
     446        case ALL_WRITABLE_DOUBLE_INDEXING_TYPES: {
     447            if (i >= butterfly->vectorLength())
     448                return false;
     449            if (!v.isNumber()) {
     450                convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
     451                return true;
     452            }
     453            double value = v.asNumber();
     454            if (value != value) {
     455                convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
     456                return true;
     457            }
     458            butterfly->contiguousDouble().at(this, i) = value;
     459            if (i >= butterfly->publicLength())
     460                butterfly->setPublicLength(i + 1);
     461            return true;
     462        }
    428463        case NonArrayWithArrayStorage:
    429464        case ArrayWithArrayStorage:
    430             return i < butterfly->vectorLength();
     465            if (i >= butterfly->vectorLength())
     466                return false;
     467            setIndexQuicklyForArrayStorageIndexingType(vm, i, v);
     468            return true;
    431469        case NonArrayWithSlowPutArrayStorage:
    432470        case ArrayWithSlowPutArrayStorage:
    433             return i < butterfly->arrayStorage()->vectorLength()
    434                 && !!butterfly->arrayStorage()->m_vector[i];
     471            if (i >= butterfly->arrayStorage()->vectorLength() || !butterfly->arrayStorage()->m_vector[i])
     472                return false;
     473            setIndexQuicklyForArrayStorageIndexingType(vm, i, v);
     474            return true;
    435475        default:
    436             if (isCopyOnWrite(indexingMode()))
    437                 return false;
    438             RELEASE_ASSERT_NOT_REACHED();
     476            RELEASE_ASSERT(isCopyOnWrite(indexingMode()));
    439477            return false;
    440478        }
    441479    }
    442        
     480
    443481    void setIndexQuickly(VM& vm, unsigned i, JSValue v)
    444482    {
  • trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h

    r284237 r284330  
    466466}
    467467
    468 inline bool JSObject::canSetIndexQuicklyForTypedArray(unsigned i, JSValue value) const
    469 {
    470     switch (type()) {
    471 #define CASE_TYPED_ARRAY_TYPE(name) \
    472     case name ## ArrayType :\
    473         return jsCast<const JS ## name ## Array *>(this)->canSetIndexQuickly(i, value);
    474         FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE)
    475 #undef CASE_TYPED_ARRAY_TYPE
    476     default:
    477         return false;
    478     }
    479 }
    480 
    481 inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i) const
    482 {
     468inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i, ArrayProfile* arrayProfile) const
     469{
     470#if USE(LARGE_TYPED_ARRAYS)
     471    if (i > ArrayProfile::s_smallTypedArrayMaxLength && arrayProfile)
     472        arrayProfile->setMayBeLargeTypedArray();
     473#else
     474    UNUSED_PARAM(arrayProfile);
     475#endif
     476
    483477    switch (type()) {
    484478#define CASE_TYPED_ARRAY_TYPE(name) \
     
    513507    }
    514508}
    515    
     509
     510inline void JSObject::setIndexQuicklyForArrayStorageIndexingType(VM& vm, unsigned i, JSValue v)
     511{
     512    ArrayStorage* storage = this->butterfly()->arrayStorage();
     513    WriteBarrier<Unknown>& x = storage->m_vector[i];
     514    JSValue old = x.get();
     515    x.set(vm, this, v);
     516    if (!old) {
     517        ++storage->m_numValuesInVector;
     518        if (i >= storage->length())
     519            storage->setLength(i + 1);
     520    }
     521}
     522
     523inline bool JSObject::trySetIndexQuicklyForTypedArray(unsigned i, JSValue v, ArrayProfile* arrayProfile)
     524{
     525    switch (type()) {
     526#if USE(LARGE_TYPED_ARRAYS)
     527#define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \
     528        if ((i > ArrayProfile::s_smallTypedArrayMaxLength) && arrayProfile)\
     529            arrayProfile->setMayBeLargeTypedArray();\
     530    } while (false)
     531#else
     532#define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \
     533    UNUSED_PARAM(arrayProfile);\
     534    } while (false)
     535#endif
     536#define CASE_TYPED_ARRAY_TYPE(name) \
     537    case name ## ArrayType : { \
     538        auto* typedArray = jsCast<JS ## name ## Array *>(this);\
     539        if (!typedArray->canSetIndexQuickly(i, v))\
     540            return false;\
     541        typedArray->setIndexQuickly(i, v);\
     542        UPDATE_ARRAY_PROFILE(i, arrayProfile);\
     543        return true;\
     544    }
     545    FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE)
     546#undef CASE_TYPED_ARRAY_TYPE
     547#undef UPDATE_ARRAY_PROFILE
     548    default:
     549        return false;
     550    }
     551}
     552
    516553inline void JSObject::validatePutOwnDataProperty(VM& vm, PropertyName propertyName, JSValue value)
    517554{
  • trunk/Source/JavaScriptCore/runtime/Operations.h

    r284237 r284330  
    899899    if (base->isObject()) {
    900900        JSObject* object = asObject(base);
    901         if (object->canGetIndexQuickly(index))
    902             return JSValue::encode(object->getIndexQuickly(index));
     901        if (JSValue result = object->tryGetIndexQuickly(index))
     902            return JSValue::encode(result);
    903903    }
    904904
  • trunk/Source/JavaScriptCore/wasm/WasmPageCount.h

    r284237 r284330  
    2727
    2828#if ENABLE(WEBASSEMBLY)
     29
     30#include "ArrayBuffer.h"
    2931
    3032#include <limits.h>
     
    9799    static constexpr uint32_t pageSize = 64 * KB;
    98100private:
    99     static constexpr uint32_t maxPageCount = static_cast<uint32_t>((1ull << 32) / pageSize);
     101    static constexpr uint32_t maxPageCount = static_cast<uint32_t>(MAX_ARRAY_BUFFER_SIZE / static_cast<uint64_t>(pageSize));
    100102
    101103    uint32_t m_pageCount;
  • trunk/Source/WTF/ChangeLog

    r284326 r284330  
     12021-10-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        Allow WASM to use up to 4GB
     4        https://bugs.webkit.org/show_bug.cgi?id=229353
     5        rdar://81603447
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        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.
     10
     11        * wtf/CheckedArithmetic.h:
     12        (WTF::isInBounds):
     13        (WTF::convertSafely):
     14        (WTF::isSumSmallerThanOrEqual):
     15
    1162021-10-16  Tim Horton  <timothy_horton@apple.com>
    217
  • trunk/Source/WTF/wtf/CheckedArithmetic.h

    r284237 r284330  
    11/*
    2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    145145template <typename Target, typename Source, bool isTargetBigger = sizeof(Target) >= sizeof(Source), bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker;
    146146template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, false> {
    147     static bool inBounds(Source value)
     147    static bool constexpr inBounds(Source value)
    148148    {
    149149        // Same signedness so implicit type conversion will always increase precision to widest type.
     
    152152};
    153153template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, true> {
    154     static bool inBounds(Source value)
     154    static bool constexpr inBounds(Source value)
    155155    {
    156156        // Same signedness so implicit type conversion will always increase precision to widest type.
     
    160160
    161161template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, true> {
    162     static bool inBounds(Source value)
     162    static bool constexpr inBounds(Source value)
    163163    {
    164164        // When converting value to unsigned Source, value will become a big value if value is negative.
     
    169169
    170170template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, false> {
    171     static bool inBounds(Source value)
     171    static bool constexpr inBounds(Source value)
    172172    {
    173173        // The unsigned Source type has greater precision than the target so max(Target) -> Source will widen.
     
    177177
    178178template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, false> {
    179     static bool inBounds(Source)
     179    static bool constexpr inBounds(Source)
    180180    {
    181181        // Same sign, greater or same precision.
     
    185185
    186186template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, true> {
    187     static bool inBounds(Source)
     187    static bool constexpr inBounds(Source)
    188188    {
    189189        // Same sign, greater or same precision.
     
    193193
    194194template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, false> {
    195     static bool inBounds(Source value)
     195    static bool constexpr inBounds(Source value)
    196196    {
    197197        // Target is signed with greater or same precision. If strictly greater, it is always safe.
     
    203203
    204204template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, true> {
    205     static bool inBounds(Source value)
     205    static bool constexpr inBounds(Source value)
    206206    {
    207207        // Target is unsigned with greater precision.
     
    210210};
    211211
    212 template <typename Target, typename Source> static inline bool isInBounds(Source value)
     212template <typename Target, typename Source> static inline constexpr bool isInBounds(Source value)
    213213{
    214214    return BoundsChecker<Target, Source>::inBounds(value);
    215215}
    216216
    217 template <typename Target, typename Source> static inline bool convertSafely(Source input, Target& output)
     217template <typename Target, typename Source> static inline constexpr bool convertSafely(Source input, Target& output)
    218218{
    219219    if (!isInBounds<Target>(input))
     
    997997}
    998998
     999template<typename T> bool isSumSmallerThanOrEqual(T a, T b, T bound)
     1000{
     1001    Checked<T, RecordOverflow> sum = a;
     1002    sum += b;
     1003    return !sum.hasOverflowed() && sum.value() <= bound;
     1004}
     1005
    9991006}
    10001007
     
    10181025using WTF::productOverflows;
    10191026using WTF::sumOverflows;
     1027using WTF::isSumSmallerThanOrEqual;
  • trunk/Source/WTF/wtf/PlatformUse.h

    r284306 r284330  
    142142#endif
    143143
     144// FIXME: this should instead be based on SIZE_MAX == UINT64_MAX
     145// But this requires including <cstdint> and Platform.h is included in all kind of weird places, including non-cpp files
     146// And in practice CPU(ADDRESS64) is equivalent on all platforms we support (verified by static_asserts in ArrayBuffer.h)
     147#if CPU(ADDRESS64)
     148#define USE_LARGE_TYPED_ARRAYS 1
     149#else
     150#define USE_LARGE_TYPED_ARRAYS 0
     151#endif
     152
    144153#if USE(JSVALUE64)
    145154/* FIXME: Enable BIGINT32 optimization again after we ensure Speedometer2 and JetStream2 regressions are fixed. */
  • trunk/Source/WebCore/ChangeLog

    r284327 r284330  
     12021-10-16  Robin Morisset  <rmorisset@apple.com>
     2
     3        Allow WASM to use up to 4GB
     4        https://bugs.webkit.org/show_bug.cgi?id=229353
     5        rdar://81603447
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        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.
     10        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).
     11
     12        I also had to add a test in PixelBuffer.cpp that the size of the ArrayBuffer it will try to allocate is < INT32_MAX.
     13        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.
     14
     15        No new tests, as the code is already extensively covered by existing tests, and I implemented no new features.
     16
     17        * Modules/webaudio/AudioBuffer.cpp:
     18        (WebCore::AudioBuffer::copyFromChannel):
     19        (WebCore::AudioBuffer::copyToChannel):
     20        * Modules/webaudio/RealtimeAnalyser.cpp:
     21        (WebCore::RealtimeAnalyser::getByteFrequencyData):
     22        (WebCore::RealtimeAnalyser::getFloatTimeDomainData):
     23        (WebCore::RealtimeAnalyser::getByteTimeDomainData):
     24        * bindings/js/SerializedScriptValue.cpp:
     25        (WebCore::CloneSerializer::dumpArrayBufferView):
     26        (WebCore::CloneSerializer::dumpImageBitmap):
     27        (WebCore::CloneSerializer::dumpIfTerminal):
     28        (WebCore::CloneDeserializer::readArrayBufferImpl):
     29        (WebCore::CloneDeserializer::readArrayBuffer):
     30        (WebCore::CloneDeserializer::readArrayBufferViewImpl):
     31        (WebCore::CloneDeserializer::readArrayBufferView):
     32        * bindings/js/SerializedScriptValue.h:
     33        (WebCore::SerializedScriptValue::encode const):
     34        (WebCore::SerializedScriptValue::decode):
     35        * fileapi/NetworkSendQueue.cpp:
     36        (WebCore::NetworkSendQueue::enqueue):
     37        * platform/graphics/PixelBuffer.cpp:
     38        (WebCore::PixelBuffer::tryCreate):
     39        * platform/graphics/iso/ISOBox.h:
     40
    1412021-10-16  Alan Bujtas  <zalan@apple.com>
    242
  • trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp

    r284237 r284330  
    199199        return { };
    200200   
    201     unsigned count = dataLength - bufferOffset;
     201    size_t count = dataLength - bufferOffset;
    202202    count = std::min(destination.get().length(), count);
    203203   
     
    227227        return { };
    228228   
    229     unsigned count = dataLength - bufferOffset;
     229    size_t count = dataLength - bufferOffset;
    230230    count = std::min(source.get().length(), count);
    231231   
  • trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp

    r284237 r284330  
    197197   
    198198    // Convert from linear magnitude to unsigned-byte decibels.
    199     unsigned sourceLength = magnitudeBuffer().size();
    200     size_t length = std::min(sourceLength, destinationArray.length());
     199    size_t sourceLength = magnitudeBuffer().size();
     200    size_t destinationLength = destinationArray.length();
     201    size_t length = std::min(sourceLength, destinationLength);
    201202    if (length > 0) {
    202203        const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 / (m_maxDecibels - m_minDecibels);
     
    228229    ASSERT(isMainThread());
    229230   
    230     unsigned fftSize = this->fftSize();
    231     size_t length = std::min(fftSize, destinationArray.length());
     231    size_t destinationLength = destinationArray.length();
     232    size_t fftSize = this->fftSize();
     233    size_t length = std::min(fftSize, destinationLength);
    232234    if (length > 0) {
    233235        bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize;
     
    252254    ASSERT(isMainThread());
    253255
    254     unsigned fftSize = this->fftSize();
    255     size_t length = std::min(fftSize, destinationArray.length());
     256    size_t destinationLength = destinationArray.length();
     257    size_t fftSize = this->fftSize();
     258    size_t length = std::min(fftSize, destinationLength);
    256259    if (length > 0) {
    257260        bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize;
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r284237 r284330  
    9595#include <JavaScriptCore/YarrFlags.h>
    9696#include <limits>
     97#include <wtf/CheckedArithmetic.h>
    9798#include <wtf/CompletionHandler.h>
    9899#include <wtf/MainThread.h>
     
    343344 * Version 8. added support for ImageData's colorSpace attribute.
    344345 * Version 9. added support for ImageBitmap color space.
     346 * Version 10. changed the length (and offsets) of ArrayBuffers (and ArrayBufferViews) from 32 to 64 bits
    345347 */
    346 static const unsigned CurrentVersion = 9;
     348static const unsigned CurrentVersion = 10;
    347349static const unsigned TerminatorTag = 0xFFFFFFFF;
    348350static const unsigned StringPoolTag = 0xFFFFFFFE;
     
    400402 *    | MessagePortReferenceTag <value:uint32_t>
    401403 *    | ArrayBuffer
    402  *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
     404 *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint64_t> <byteLength:uint64_t> (ArrayBuffer | ObjectReference)
    403405 *    | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
    404406 *    | DOMPoint
     
    464466 *
    465467 * ArrayBuffer :-
    466  *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
     468 *    ArrayBufferTag <length:uint64_t> <contents:byte{length}>
    467469 *    ArrayBufferTransferTag <value:uint32_t>
    468470 *    SharedArrayBufferTag <value:uint32_t>
     
    911913    void dumpBigInt32Data(int32_t integer)
    912914    {
    913         static_assert(sizeof(uint64_t) == sizeof(unsigned long long));
    914915        write(static_cast<uint8_t>(integer < 0));
    915916        if (!integer) {
     
    921922        if (value < 0)
    922923            value = -value;
    923         write(static_cast<unsigned long long>(value));
     924        write(static_cast<uint64_t>(value));
    924925    }
    925926#endif
     
    927928    void dumpHeapBigIntData(JSBigInt* bigInt)
    928929    {
    929         static_assert(sizeof(uint64_t) == sizeof(unsigned long long));
    930930        write(static_cast<uint8_t>(bigInt->sign()));
    931931        if constexpr (sizeof(JSBigInt::Digit) == sizeof(uint64_t)) {
    932932            write(static_cast<uint32_t>(bigInt->length()));
    933933            for (unsigned index = 0; index < bigInt->length(); ++index)
    934                 write(static_cast<unsigned long long>(bigInt->digit(index)));
     934                write(static_cast<uint64_t>(bigInt->digit(index)));
    935935        } else {
    936936            ASSERT(sizeof(JSBigInt::Digit) == sizeof(uint32_t));
     
    945945                else {
    946946                    value = (static_cast<uint64_t>(bigInt->digit(index)) << 32) | value;
    947                     write(static_cast<unsigned long long>(value));
     947                    write(static_cast<uint64_t>(value));
    948948                    value = 0;
    949949                }
    950950            }
    951951            if (bigInt->length() & 0x1)
    952                 write(static_cast<unsigned long long>(value));
     952                write(static_cast<uint64_t>(value));
    953953        }
    954954    }
     
    999999
    10001000        RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj);
    1001         write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
    1002         write(static_cast<uint32_t>(arrayBufferView->byteLength()));
     1001        uint64_t byteOffset = arrayBufferView->byteOffset();
     1002        write(byteOffset);
     1003        uint64_t byteLength = arrayBufferView->byteLength();
     1004        write(byteLength);
    10031005        RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer();
    10041006        if (!arrayBuffer) {
     
    11321134        write(buffer->colorSpace());
    11331135
    1134         write(static_cast<uint32_t>(arrayBuffer->byteLength()));
    1135         write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
     1136        CheckedUint32 byteLength = arrayBuffer->byteLength();
     1137        if (byteLength.hasOverflowed()) {
     1138            code = SerializationReturnCode::ValidationError;
     1139            return;
     1140        }
     1141        write(byteLength);
     1142        write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength);
    11361143    }
    11371144
     
    12571264                write(blob->url().string());
    12581265                write(blob->type());
    1259                 write(blob->size());
     1266                static_assert(sizeof(uint64_t) == sizeof(decltype(blob->size())));
     1267                uint64_t size = blob->size();
     1268                write(size);
    12601269                return true;
    12611270            }
     
    12641273                write(data->width());
    12651274                write(data->height());
    1266                 write(data->data().length());
    1267                 write(data->data().data(), data->data().length());
     1275                CheckedUint32 dataLength = data->data().length();
     1276                if (dataLength.hasOverflowed()) {
     1277                    code = SerializationReturnCode::DataCloneError;
     1278                    return true;
     1279                }
     1280                write(dataLength);
     1281                write(data->data().data(), dataLength);
    12681282                write(data->colorSpace());
    12691283                return true;
     
    13121326               
    13131327                write(ArrayBufferTag);
    1314                 write(arrayBuffer->byteLength());
    1315                 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
     1328                uint64_t byteLength = arrayBuffer->byteLength();
     1329                write(byteLength);
     1330                write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength);
    13161331                return true;
    13171332            }
     
    15031518    }
    15041519
    1505     void write(unsigned long long i)
     1520    void write(uint64_t i)
    15061521    {
    15071522        writeLittleEndian(m_buffer, i);
     
    23922407    }
    23932408
    2394     bool read(unsigned long long& i)
     2409    bool read(uint64_t& i)
    23952410    {
    23962411        return readLittleEndian(i);
     
    25562571    }
    25572572
    2558     bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
    2559     {
    2560         uint32_t length;
     2573    template<typename LengthType>
     2574    bool readArrayBufferImpl(RefPtr<ArrayBuffer>& arrayBuffer)
     2575    {
     2576        LengthType length;
    25612577        if (!read(length))
    25622578            return false;
     
    25702586    }
    25712587
    2572     bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
     2588    bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
     2589    {
     2590        if (m_version < 10)
     2591            return readArrayBufferImpl<uint32_t>(arrayBuffer);
     2592        return readArrayBufferImpl<uint64_t>(arrayBuffer);
     2593    }
     2594
     2595    template <typename LengthType>
     2596    bool readArrayBufferViewImpl(VM& vm, JSValue& arrayBufferView)
    25732597    {
    25742598        ArrayBufferViewSubtag arrayBufferViewSubtag;
    25752599        if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
    25762600            return false;
    2577         uint32_t byteOffset;
     2601        LengthType byteOffset;
    25782602        if (!read(byteOffset))
    25792603            return false;
    2580         uint32_t byteLength;
     2604        LengthType byteLength;
    25812605        if (!read(byteLength))
    25822606            return false;
     
    25882612        if (!elementSize)
    25892613            return false;
    2590         unsigned length = byteLength / elementSize;
     2614        LengthType length = byteLength / elementSize;
    25912615        if (length * elementSize != byteLength)
    25922616            return false;
     
    26332657            return false;
    26342658        }
     2659    }
     2660
     2661    bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
     2662    {
     2663        if (m_version < 10)
     2664            return readArrayBufferViewImpl<uint32_t>(vm, arrayBufferView);
     2665        return readArrayBufferViewImpl<uint64_t>(vm, arrayBufferView);
    26352666    }
    26362667
     
    33463377        RefPtr<ArrayBuffer> arrayBuffer;
    33473378
    3348         if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBuffer(arrayBuffer)) {
     3379        if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBufferImpl<uint32_t>(arrayBuffer)) {
    33493380            fail();
    33503381            return JSValue();
     
    34123443        static_assert(sizeof(JSBigInt::Digit) == sizeof(uint64_t));
    34133444        if (lengthInUint64 == 1) {
    3414             static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
    3415             unsigned long long digit64 = 0;
     3445            uint64_t digit64 = 0;
    34163446            if (!read(digit64))
    34173447                return JSValue();
     
    34483478            }
    34493479            for (uint32_t index = 0; index < lengthInUint64; ++index) {
    3450                 static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
    3451                 unsigned long long digit64 = 0;
     3480                uint64_t digit64 = 0;
    34523481                if (!read(digit64))
    34533482                    return JSValue();
     
    34623491            }
    34633492            for (uint32_t index = 0; index < lengthInUint64; ++index) {
    3464                 static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
    3465                 unsigned long long digit64 = 0;
     3493                uint64_t digit64 = 0;
    34663494                if (!read(digit64))
    34673495                    return JSValue();
     
    36193647            if (!readStringData(type))
    36203648                return JSValue();
    3621             unsigned long long size = 0;
     3649            uint64_t size = 0;
    36223650            if (!read(size))
    36233651                return JSValue();
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.h

    r284237 r284330  
    168168        encoder << static_cast<uint64_t>(m_arrayBufferContentsArray->size());
    169169        for (const auto &arrayBufferContents : *m_arrayBufferContentsArray) {
    170             encoder << arrayBufferContents.sizeInBytes();
     170            encoder << static_cast<uint64_t>(arrayBufferContents.sizeInBytes());
    171171            encoder.encodeFixedLengthData(static_cast<const uint8_t*>(arrayBufferContents.data()), arrayBufferContents.sizeInBytes(), 1);
    172172        }
     
    200200        arrayBufferContentsArray = makeUnique<ArrayBufferContentsArray>();
    201201        while (arrayLength--) {
    202             unsigned bufferSize;
     202            uint64_t bufferSize;
    203203            if (!decoder.decode(bufferSize))
     204                return nullptr;
     205            CheckedSize checkedBufferSize = bufferSize;
     206            if (checkedBufferSize.hasOverflowed())
    204207                return nullptr;
    205208            if (!decoder.template bufferIsLargeEnoughToContain<uint8_t>(bufferSize))
     
    213216                return nullptr;
    214217            }
    215             arrayBufferContentsArray->append({ buffer, bufferSize, ArrayBuffer::primitiveGigacageDestructor() });
     218            arrayBufferContentsArray->append({ buffer, checkedBufferSize, ArrayBuffer::primitiveGigacageDestructor() });
    216219        }
    217220    }
  • trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp

    r284237 r284330  
    6969    auto byteLength = blob.size();
    7070    if (!byteLength) {
    71         enqueue(JSC::ArrayBuffer::create(0U, 1), 0, 0);
     71        // The cast looks weird, but is required for the overloading resolution to succeed.
     72        // Without it, there is an ambiguity where ArrayBuffer::create(const void* source, size_t byteLength) could be called instead.
     73        enqueue(JSC::ArrayBuffer::create(static_cast<size_t>(0U), 1), 0, 0);
    7274        return;
    7375    }
  • trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp

    r284237 r284330  
    7575    if (bufferSize.hasOverflowed())
    7676        return std::nullopt;
     77    if (bufferSize > std::numeric_limits<int32_t>::max())
     78        return std::nullopt;
    7779    auto pixelArray = Uint8ClampedArray::tryCreateUninitialized(bufferSize);
    7880    if (!pixelArray)
  • trunk/Source/WebCore/platform/graphics/iso/ISOBox.h

    r284237 r284330  
    2828#include "FourCC.h"
    2929#include <wtf/Forward.h>
     30#include <wtf/StdIntExtras.h>
    3031#include <wtf/TypeCasts.h>
    3132
     
    6465    {
    6566        bool readStatus = false;
    66         T value = view.template read<T>(offset, endianness == LittleEndian, &readStatus);
     67        size_t actualOffset = offset;
     68        T value = view.template read<T>(actualOffset, endianness == LittleEndian, &readStatus);
     69        RELEASE_ASSERT(isInBounds<uint32_t>(actualOffset));
     70        offset = actualOffset;
    6771        if (!readStatus)
    6872            return false;
Note: See TracChangeset for help on using the changeset viewer.