<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[284330] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/284330">284330</a></dd>
<dt>Author</dt> <dd>rmorisset@apple.com</dd>
<dt>Date</dt> <dd>2021-10-16 21:00:16 -0700 (Sat, 16 Oct 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>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:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressbigwasmmemorygrownomaxjs">trunk/JSTests/stress/big-wasm-memory-grow-no-max.js</a></li>
<li><a href="#trunkJSTestsstressbigwasmmemorygrowjs">trunk/JSTests/stress/big-wasm-memory-grow.js</a></li>
<li><a href="#trunkJSTestsstressbigwasmmemoryjs">trunk/JSTests/stress/big-wasm-memory.js</a></li>
<li><a href="#trunkJSTestswasmregresswasmmemoryrequestedmorethanMAX_ARRAY_BUFFER_SIZE2js">trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js</a></li>
<li><a href="#trunkJSTestswasmregresswasmmemoryrequestedmorethanMAX_ARRAY_BUFFER_SIZEjs">trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfaststorageserializedscriptvaluehtml">trunk/LayoutTests/fast/storage/serialized-script-value.html</a></li>
<li><a href="#trunkLayoutTestswebaudioOfflineAudioContextbadbufferlengthexpectedtxt">trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt</a></li>
<li><a href="#trunkLayoutTestswebaudioOfflineAudioContextbadbuffercrashexpectedtxt">trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblercpp">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/MacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64Eh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeAccessCasecpp">trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArrayProfileh">trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModecpp">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModeh">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCommonh">trunk/Source/JavaScriptCore/dfg/DFGCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGenerationInfoh">trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationcpp">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGHeapLocationh">trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSSALoweringPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGValidatecpp">trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitIntrinsicEmittercpp">trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntOfflineAsmConfigh">trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayBuffercpp">trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayBufferh">trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayBufferViewcpp">trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayBufferViewh">trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeAtomicsObjectcpp">trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDataViewcpp">trunk/Source/JavaScriptCore/runtime/DataView.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDataViewh">trunk/Source/JavaScriptCore/runtime/DataView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGenericTypedArrayViewh">trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewcpp">trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh">trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh">trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDataViewcpp">trunk/Source/JavaScriptCore/runtime/JSDataView.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDataViewh">trunk/Source/JavaScriptCore/runtime/JSDataView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSDataViewPrototypecpp">trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewConstructorInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectInlinesh">trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOperationsh">trunk/Source/JavaScriptCore/runtime/Operations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmPageCounth">trunk/Source/JavaScriptCore/wasm/WasmPageCount.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfCheckedArithmetich">trunk/Source/WTF/wtf/CheckedArithmetic.h</a></li>
<li><a href="#trunkSourceWTFwtfPlatformUseh">trunk/Source/WTF/wtf/PlatformUse.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioAudioBuffercpp">trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreModuleswebaudioRealtimeAnalysercpp">trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsSerializedScriptValuecpp">trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsSerializedScriptValueh">trunk/Source/WebCore/bindings/js/SerializedScriptValue.h</a></li>
<li><a href="#trunkSourceWebCorefileapiNetworkSendQueuecpp">trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsPixelBuffercpp">trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsisoISOBoxh">trunk/Source/WebCore/platform/graphics/iso/ISOBox.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstresstypedarrayalwayslargejs">trunk/JSTests/stress/typed-array-always-large.js</a></li>
<li><a href="#trunkJSTestsstresstypedarrayeventuallylargejs">trunk/JSTests/stress/typed-array-eventually-large.js</a></li>
<li><a href="#trunkJSTestsstresstypedarraylargeeventuallyoobjs">trunk/JSTests/stress/typed-array-large-eventually-oob.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/ChangeLog     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2021-10-16  Robin Morisset  <rmorisset@apple.com>
+
+        Allow WASM to use up to 4GB
+        https://bugs.webkit.org/show_bug.cgi?id=229353
+        rdar://81603447
+
+        Reviewed by Yusuke Suzuki.
+
+        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:
+
</ins><span class="cx"> 2021-10-15  Robin Morisset  <rmorisset@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Revert r284230, my last fixes to the watch build make it break tests
</span></span></pre></div>
<a id="trunkJSTestsstressbigwasmmemorygrownomaxjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/big-wasm-memory-grow-no-max.js (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/big-wasm-memory-grow-no-max.js      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/stress/big-wasm-memory-grow-no-max.js 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,4 +1,5 @@
</span><del>-//@ skip if $memoryLimited
</del><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
</ins><span class="cx"> 
</span><span class="cx"> function test() {
</span><span class="cx"> 
</span><span class="lines">@@ -24,19 +25,25 @@
</span><span class="cx">     for (var i = 0; i < 10000; ++i)
</span><span class="cx">         foo(okArray);
</span><span class="cx"> 
</span><ins>+    let maxSize = 0x10000;
+    {
+        var memory = new WebAssembly.Memory({ initial: 0x1000 });
+        memory.grow(maxSize - 0x1000);
+        var result = foo(new Uint8Array(memory.buffer));
+        if (result !== void 0)
+            throw "Error: bad result at end: " + result;
+    }
+
</ins><span class="cx">     var ok = false;
</span><span class="cx">     try {
</span><span class="cx">         var memory = new WebAssembly.Memory({ initial: 0x1000 });
</span><del>-        memory.grow(0x7000);
</del><ins>+        memory.grow(maxSize - 0x1000 + 1);
</ins><span class="cx">         var result = foo(new Uint8Array(memory.buffer));
</span><del>-        if (result !== void 0)
-            throw "Error: bad result at end: " + result;
</del><span class="cx">         ok = true;
</span><span class="cx">     } catch (e) {
</span><del>-        if (e.toString() != "RangeError: Out of memory")
</del><ins>+        if (e.toString() != "RangeError: WebAssembly.Memory.grow expects the grown size to be a valid page count")
</ins><span class="cx">             throw e;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     if (ok)
</span><span class="cx">         throw "Error: did not throw error";
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsstressbigwasmmemorygrowjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/big-wasm-memory-grow.js (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/big-wasm-memory-grow.js     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/stress/big-wasm-memory-grow.js        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,4 +1,5 @@
</span><del>-//@ skip if $memoryLimited
</del><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
</ins><span class="cx"> 
</span><span class="cx"> function test() {
</span><span class="cx"> 
</span><span class="lines">@@ -24,19 +25,26 @@
</span><span class="cx">     for (var i = 0; i < 10000; ++i)
</span><span class="cx">         foo(okArray);
</span><span class="cx"> 
</span><ins>+
+    let maxSize = 0x10000;
+    {
+        var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize });
+        memory.grow(maxSize - 0x1000);
+        var result = foo(new Uint8Array(memory.buffer));
+        if (result !== void 0)
+            throw "Error: bad result at end: " + result;
+    }
+
</ins><span class="cx">     var ok = false;
</span><span class="cx">     try {
</span><del>-        var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: 0x8000 });
-        memory.grow(0x7000);
</del><ins>+        var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize+1 });
+        memory.grow(maxSize + 1 - 0x1000);
</ins><span class="cx">         var result = foo(new Uint8Array(memory.buffer));
</span><del>-        if (result !== void 0)
-            throw "Error: bad result at end: " + result;
</del><span class="cx">         ok = true;
</span><span class="cx">     } catch (e) {
</span><del>-        if (e.toString() != "RangeError: Out of memory")
</del><ins>+        if (e.toString() != "RangeError: WebAssembly.Memory 'maximum' page count is too large")
</ins><span class="cx">             throw e;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     if (ok)
</span><span class="cx">         throw "Error: did not throw error";
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsstressbigwasmmemoryjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/big-wasm-memory.js (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/big-wasm-memory.js  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/stress/big-wasm-memory.js     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,4 +1,5 @@
</span><del>-//@ skip if $memoryLimited
</del><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
</ins><span class="cx"> 
</span><span class="cx"> function test() {
</span><span class="cx"> 
</span><span class="lines">@@ -24,17 +25,21 @@
</span><span class="cx">     for (var i = 0; i < 10000; ++i)
</span><span class="cx">         foo(okArray);
</span><span class="cx"> 
</span><ins>+    let maxSize = 0x10000;
+    {
+        var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize, maximum: maxSize }).buffer));
+        if (result !== void 0)
+            throw "Error: bad result at end: " + result;
+    }
+
</ins><span class="cx">     var ok = false;
</span><span class="cx">     try {
</span><del>-        var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: 0x8000, maximum: 0x8000 }).buffer));
-        if (result !== void 0)
-            throw "Error: bad result at end: " + result;
</del><ins>+        var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize+1, maximum: maxSize+1 }).buffer));
</ins><span class="cx">         ok = true;
</span><span class="cx">     } catch (e) {
</span><del>-        if (e.toString() != "RangeError: Out of memory")
</del><ins>+        if (e.toString() != "RangeError: WebAssembly.Memory 'initial' page count is too large")
</ins><span class="cx">             throw e;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     if (ok)
</span><span class="cx">         throw "Error: did not throw error";
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkJSTestsstresstypedarrayalwayslargejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/typed-array-always-large.js (0 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/typed-array-always-large.js                         (rev 0)
+++ trunk/JSTests/stress/typed-array-always-large.js    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
+
+function getArrayLength(array)
+{
+    return array.length;
+}
+noInline(getArrayLength);
+function getByVal(array, index)
+{
+    return array[index];
+}
+noInline(getByVal);
+function putByVal(array, index, value)
+{
+    array[index] = value;
+}
+noInline(putByVal);
+
+let oneGiga = 1024 * 1024 * 1024;
+
+function test(array, actualLength, string)
+{
+    for (var i = 0; i < 100000; ++i) {
+        var l = getArrayLength(array);
+        if (l != actualLength)
+            throw ("Wrong array length: " + l + " instead of the expected " + actualLength + " in case " + string);
+        var index = (2 * oneGiga) + i;
+        var value = i % 100;
+        putByVal(array, index, value);
+        var result = getByVal(array, index);
+        if (result != value)
+            throw ("Expected " + value + " but got " + result + " in case " + string);
+    }
+}
+
+let threeGigs = 3 * oneGiga;
+let fourGigs = 4 * oneGiga;
+
+test(new Int8Array(threeGigs), threeGigs, "Int8Array/3GB");
+test(new Uint8Array(fourGigs), fourGigs, "Uint8Array/4GB");
+test(new Uint8ClampedArray(threeGigs), threeGigs, "Uint8ClampedArray/3GB");
</ins></span></pre></div>
<a id="trunkJSTestsstresstypedarrayeventuallylargejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/typed-array-eventually-large.js (0 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/typed-array-eventually-large.js                             (rev 0)
+++ trunk/JSTests/stress/typed-array-eventually-large.js        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
+
+function getArrayLength(array)
+{
+    return array.length;
+}
+noInline(getArrayLength);
+function getByVal(array, index)
+{
+    return array[index];
+}
+noInline(getByVal);
+function putByVal(array, index, value)
+{
+    array[index] = value;
+}
+noInline(putByVal);
+
+let oneGiga = 1024 * 1024 * 1024;
+
+function test(array, actualLength, string)
+{
+    for (var i = 0; i < 100000; ++i) {
+        var l = getArrayLength(array);
+        if (l != actualLength)
+            throw ("Wrong array length: " + l + " instead of the expected " + actualLength + " in case " + string);
+        var index = i;
+        var value = i % 100;
+        putByVal(array, index, value);
+        var result = getByVal(array, index);
+        if (result != value)
+            throw ("Expected " + value + " but got " + result + " in case " + string);
+    }
+    var value = 42;
+    var index = 2 * oneGiga + 10;
+    putByVal(array, index, value);
+    var result = getByVal(array, index);
+    if (result != value)
+        throw ("Expected " + value + " but got " + result + " in case " + string);
+}
+
+let threeGigs = 3 * oneGiga;
+let fourGigs = 4 * oneGiga;
+
+test(new Int8Array(threeGigs), threeGigs, "Int8Array/3GB");
+test(new Uint8Array(fourGigs), fourGigs, "Uint8Array/4GB");
+test(new Uint8ClampedArray(threeGigs), threeGigs, "Uint8ClampedArray/3GB");
</ins></span></pre></div>
<a id="trunkJSTestsstresstypedarraylargeeventuallyoobjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/typed-array-large-eventually-oob.js (0 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/typed-array-large-eventually-oob.js                         (rev 0)
+++ trunk/JSTests/stress/typed-array-large-eventually-oob.js    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+//@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64")
+//@ runDefault()
+function getArrayLength(array)
+{
+    return array.length;
+}
+noInline(getArrayLength);
+function getByVal(array, index)
+{
+    return array[index];
+}
+noInline(getByVal);
+function putByVal(array, index, value)
+{
+    'use strict';
+    array[index] = value;
+}
+noInline(putByVal);
+
+let oneGiga = 1024 * 1024 * 1024;
+
+function test(array, actualLength, string)
+{
+    for (var i = 0; i < 100000; ++i) {
+        var l = getArrayLength(array);
+        if (l != actualLength)
+            throw ("Wrong array length: " + l + " instead of the expected " + actualLength + " in case " + string);
+        var index = i;
+        var value = i % 100;
+        putByVal(array, index, value);
+        var result = getByVal(array, index);
+        if (result != value)
+            throw ("Expected " + value + " but got " + result + " in case " + string);
+    }
+    var value = 42;
+    var index = actualLength + 10;
+    putByVal(array, index, value);
+    var result = getByVal(array, index);
+    if (result != undefined)
+        throw ("In out-of-bounds case, expected undefined but got " + result + " in case " + string);
+}
+
+let threeGigs = 3 * oneGiga;
+let fourGigs = 4 * oneGiga;
+
+test(new Int8Array(threeGigs), threeGigs, "Int8Array/3GB");
+test(new Uint8Array(fourGigs), fourGigs, "Uint8Array/4GB");
+test(new Uint8ClampedArray(threeGigs), threeGigs, "Uint8ClampedArray/3GB");
</ins></span></pre></div>
<a id="trunkJSTestswasmregresswasmmemoryrequestedmorethanMAX_ARRAY_BUFFER_SIZE2js"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -76,13 +76,13 @@
</span><span class="cx"> var exception;
</span><span class="cx"> try {
</span><span class="cx">     var module = new WasmModuleBuilder();
</span><del>-    module.addMemory(32768);
</del><ins>+    module.addMemory((2**16) + 1);
</ins><span class="cx">     module.instantiate();
</span><span class="cx"> } catch (e) {
</span><span class="cx">     exception = e;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-if (exception != "RangeError: Out of memory") {
</del><ins>+if (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())')") {
</ins><span class="cx">     print(exception);
</span><span class="cx">     throw "FAILED";
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJSTestswasmregresswasmmemoryrequestedmorethanMAX_ARRAY_BUFFER_SIZEjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,10 +1,10 @@
</span><span class="cx"> var exception;
</span><span class="cx"> 
</span><span class="cx"> try {
</span><del>-    new WebAssembly.Memory({ initial: 0x8000, maximum: 0x8000 }).buffer;
</del><ins>+    new WebAssembly.Memory({ initial: 0x10001, maximum: 0x10001 }).buffer;
</ins><span class="cx"> } catch (e) {
</span><span class="cx">     exception = e;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-if (exception != "RangeError: Out of memory")
-    throw "FAILED";
</del><ins>+if (exception != "RangeError: WebAssembly.Memory 'initial' page count is too large")
+    throw "FAILED, exception was: " + exception;
</ins></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/LayoutTests/ChangeLog 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2021-10-16  Robin Morisset  <rmorisset@apple.com>
+
+        Allow WASM to use up to 4GB
+        https://bugs.webkit.org/show_bug.cgi?id=229353
+        rdar://81603447
+
+        Reviewed by Yusuke Suzuki.
+
+        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:
+
</ins><span class="cx"> 2021-10-16  Tim Horton  <timothy_horton@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, revert r284181
</span></span></pre></div>
<a id="trunkLayoutTestsfaststorageserializedscriptvaluehtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/storage/serialized-script-value.html (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/storage/serialized-script-value.html      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/LayoutTests/fast/storage/serialized-script-value.html 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -6,7 +6,7 @@
</span><span class="cx">     <body>
</span><span class="cx">         <script>
</span><span class="cx"> 
</span><del>-const currentVersion = 0x09;
</del><ins>+const currentVersion = 0x0a;
</ins><span class="cx"> 
</span><span class="cx"> // Here's a little Q&D helper for future adventurers needing to rebaseline this.
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestswebaudioOfflineAudioContextbadbufferlengthexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.
</del><span class="cx"> Make sure that the length returned by OfflineAudioContext even if we failed to construct the rendering buffer.
</span><span class="cx"> 
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span></span></pre></div>
<a id="trunkLayoutTestswebaudioOfflineAudioContextbadbuffercrashexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,4 +1,3 @@
</span><del>-CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.
</del><span class="cx"> This test passes if it does not crash.
</span><span class="cx"> 
</span><span class="cx"> On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/ChangeLog       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,3 +1,275 @@
</span><ins>+2021-10-16  Robin Morisset  <rmorisset@apple.com>
+
+        Allow WASM to use up to 4GB
+        https://bugs.webkit.org/show_bug.cgi?id=229353
+        rdar://81603447
+
+        Reviewed by Yusuke Suzuki.
+
+        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:
+
</ins><span class="cx"> 2021-10-15  Ross Kirsling  <ross.kirsling@sony.com>
</span><span class="cx"> 
</span><span class="cx">         Realize Mac CMake build of WebCore and WebKit
</span><span class="lines">@@ -361,7 +633,7 @@
</span><span class="cx">         Reviewed by Yusuke Suzuki.
</span><span class="cx"> 
</span><span class="cx">         While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work:
</span><del>-        - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being UCPURegister.
</del><ins>+        - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being size_t.
</ins><span class="cx">         - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size.
</span><span class="cx">             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)
</span><span class="cx">         - Similarly, GetArrayLength and GetTypedArrayByteOffset now can either return an Int32 or a larger number.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2017-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -265,9 +265,9 @@
</span><span class="cx">     // in a class requiring explicit construction in order to differentiate
</span><span class="cx">     // from pointers used as absolute addresses to memory operations
</span><span class="cx">     struct TrustedImmPtr : public TrustedImm {
</span><del>-        TrustedImmPtr() { }
</del><ins>+        constexpr TrustedImmPtr() { }
</ins><span class="cx">         
</span><del>-        explicit TrustedImmPtr(const void* value)
</del><ins>+        explicit constexpr TrustedImmPtr(const void* value)
</ins><span class="cx">             : m_value(value)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="lines">@@ -278,21 +278,21 @@
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        explicit TrustedImmPtr(std::nullptr_t)
</del><ins>+        explicit constexpr TrustedImmPtr(std::nullptr_t)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        explicit TrustedImmPtr(size_t value)
</del><ins>+        explicit constexpr TrustedImmPtr(size_t value)
</ins><span class="cx">             : m_value(reinterpret_cast<void*>(value))
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        intptr_t asIntptr()
</del><ins>+        constexpr intptr_t asIntptr()
</ins><span class="cx">         {
</span><span class="cx">             return reinterpret_cast<intptr_t>(m_value);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        void* asPtr()
</del><ins>+        constexpr void* asPtr()
</ins><span class="cx">         {
</span><span class="cx">             return const_cast<void*>(m_value);
</span><span class="cx">         }
</span><span class="lines">@@ -302,12 +302,12 @@
</span><span class="cx"> 
</span><span class="cx">     struct ImmPtr : private TrustedImmPtr
</span><span class="cx">     {
</span><del>-        explicit ImmPtr(const void* value)
</del><ins>+        explicit constexpr ImmPtr(const void* value)
</ins><span class="cx">             : TrustedImmPtr(value)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        TrustedImmPtr asTrustedImmPtr() { return *this; }
</del><ins>+        constexpr TrustedImmPtr asTrustedImmPtr() { return *this; }
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     // TrustedImm32:
</span><span class="lines">@@ -325,7 +325,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx"> #if !CPU(X86_64)
</span><del>-        explicit TrustedImm32(TrustedImmPtr ptr)
</del><ins>+        explicit constexpr TrustedImm32(TrustedImmPtr ptr)
</ins><span class="cx">             : m_value(ptr.asIntptr())
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="lines">@@ -336,17 +336,17 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     struct Imm32 : private TrustedImm32 {
</span><del>-        explicit Imm32(int32_t value)
</del><ins>+        explicit constexpr Imm32(int32_t value)
</ins><span class="cx">             : TrustedImm32(value)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> #if !CPU(X86_64)
</span><del>-        explicit Imm32(TrustedImmPtr ptr)
</del><ins>+        explicit constexpr Imm32(TrustedImmPtr ptr)
</ins><span class="cx">             : TrustedImm32(ptr)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> #endif
</span><del>-        const TrustedImm32& asTrustedImm32() const { return *this; }
</del><ins>+        constexpr const TrustedImm32& asTrustedImm32() const { return *this; }
</ins><span class="cx"> 
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="lines">@@ -357,15 +357,15 @@
</span><span class="cx">     // (which are implemented as an enum) from accidentally being passed as
</span><span class="cx">     // immediate values.
</span><span class="cx">     struct TrustedImm64 : TrustedImm {
</span><del>-        TrustedImm64() { }
</del><ins>+        constexpr TrustedImm64() { }
</ins><span class="cx">         
</span><del>-        explicit TrustedImm64(int64_t value)
</del><ins>+        explicit constexpr TrustedImm64(int64_t value)
</ins><span class="cx">             : m_value(value)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx"> #if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
</span><del>-        explicit TrustedImm64(TrustedImmPtr ptr)
</del><ins>+        explicit constexpr TrustedImm64(TrustedImmPtr ptr)
</ins><span class="cx">             : m_value(ptr.asIntptr())
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="lines">@@ -376,17 +376,17 @@
</span><span class="cx"> 
</span><span class="cx">     struct Imm64 : private TrustedImm64
</span><span class="cx">     {
</span><del>-        explicit Imm64(int64_t value)
</del><ins>+        explicit constexpr Imm64(int64_t value)
</ins><span class="cx">             : TrustedImm64(value)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> #if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
</span><del>-        explicit Imm64(TrustedImmPtr ptr)
</del><ins>+        explicit constexpr Imm64(TrustedImmPtr ptr)
</ins><span class="cx">             : TrustedImm64(ptr)
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> #endif
</span><del>-        const TrustedImm64& asTrustedImm64() const { return *this; }
</del><ins>+        constexpr const TrustedImm64& asTrustedImm64() const { return *this; }
</ins><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     // Section 2: MacroAssembler code buffer handles
</span><span class="lines">@@ -1053,9 +1053,9 @@
</span><span class="cx">         UNREACHABLE_FOR_PLATFORM();
</span><span class="cx">         return firstRegister();
</span><span class="cx">     }
</span><del>-    static bool canBlind() { return false; }
-    static bool shouldBlindForSpecificArch(uint32_t) { return false; }
-    static bool shouldBlindForSpecificArch(uint64_t) { return false; }
</del><ins>+    static constexpr bool canBlind() { return false; }
+    static constexpr bool shouldBlindForSpecificArch(uint32_t) { return false; }
+    static constexpr bool shouldBlindForSpecificArch(uint64_t) { return false; }
</ins><span class="cx"> 
</span><span class="cx">     class CachedTempRegister {
</span><span class="cx">         friend class DataLabelPtr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssembler.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssembler.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssembler.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -140,6 +140,9 @@
</span><span class="cx"> #if CPU(ARM64) || CPU(ARM_THUMB2) || CPU(X86_64) || CPU(MIPS) || CPU(RISCV64)
</span><span class="cx">     using MacroAssemblerBase::branchPtr;
</span><span class="cx"> #endif
</span><ins>+#if CPU(X86_64)
+    using MacroAssemblerBase::branch64;
+#endif
</ins><span class="cx">     using MacroAssemblerBase::branchSub32;
</span><span class="cx">     using MacroAssemblerBase::lshift32;
</span><span class="cx">     using MacroAssemblerBase::or32;
</span><span class="lines">@@ -1460,6 +1463,7 @@
</span><span class="cx">         } else
</span><span class="cx">             and64(imm.asTrustedImm32(), dest);
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx"> #endif // USE(JSVALUE64)
</span><span class="cx"> 
</span><span class="cx"> #if !CPU(X86) && !CPU(X86_64) && !CPU(ARM64)
</span><span class="lines">@@ -1727,7 +1731,7 @@
</span><span class="cx">             store64(imm.asTrustedImm64(), dest);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#endif // CPU(X86_64) || CPU(ARM64)
</del><ins>+#endif // CPU(X86_64) || CPU(ARM64) || CPU(RISCV64)
</ins><span class="cx">     
</span><span class="cx">     void store32(Imm32 imm, Address dest)
</span><span class="cx">     {
</span><span class="lines">@@ -1821,6 +1825,28 @@
</span><span class="cx">         return branch32(cond, left, right.asTrustedImm32());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if CPU(X86_64)
+    // Other 64-bit platforms don't need blinding, and have branch64(RelationalCondition, RegisterID, Imm64) directly defined in the right file.
+    // We cannot put this in MacroAssemblerX86_64.h, because it uses shouldBlind(), loadRoationBlindedConstant, etc.. which are only defined here and not there.
+    Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right)
+    {
+        if (shouldBlind(right)) {
+            if (haveScratchRegisterForBlinding()) {
+                loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegisterForBlinding());
+                return branch64(cond, left, scratchRegisterForBlinding());
+            }
+
+            // If we don't have a scratch register available for use, we'll just
+            // place a random number of nops.
+            uint32_t nopCount = random() & 3;
+            while (nopCount--)
+                nop();
+            return branch64(cond, left, right.asTrustedImm64());
+        }
+        return branch64(cond, left, right.asTrustedImm64());
+    }
+#endif // CPU(X86_64)
+
</ins><span class="cx">     void compare32(RelationalCondition cond, RegisterID left, Imm32 right, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         if (shouldBlind(right)) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -144,8 +144,8 @@
</span><span class="cx">     static constexpr RegisterID linkRegister = ARM64Registers::lr;
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Get reasonable implementations for these
</span><del>-    static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
-    static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
</del><ins>+    static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
+    static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
</ins><span class="cx"> 
</span><span class="cx">     // Integer operations:
</span><span class="cx"> 
</span><span class="lines">@@ -3305,6 +3305,11 @@
</span><span class="cx">         return Jump(makeBranch(cond));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right)
+    {
+        return branch64(cond, left, right.asTrustedImm64());
+    }
+
</ins><span class="cx">     Jump branch64(RelationalCondition cond, RegisterID left, Address right)
</span><span class="cx">     {
</span><span class="cx">         load64(right, getCachedMemoryTempRegisterIDAndInvalidate());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64Eh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -132,10 +132,10 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE void untagArrayPtrLength32(Address length, RegisterID target, bool validateAuth)
</del><ins>+    ALWAYS_INLINE void untagArrayPtrLength64(Address length, RegisterID target, bool validateAuth)
</ins><span class="cx">     {
</span><span class="cx">         auto lengthGPR = getCachedDataTempRegisterIDAndInvalidate();
</span><del>-        load32(length, lengthGPR);
</del><ins>+        load64(length, lengthGPR);
</ins><span class="cx">         auto scratch = validateAuth ? getCachedMemoryTempRegisterIDAndInvalidate() : InvalidGPRReg; 
</span><span class="cx">         untagArrayPtr(lengthGPR, target, validateAuth, scratch);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -108,9 +108,9 @@
</span><span class="cx">     static constexpr RegisterID stackPointerRegister = X86Registers::esp;
</span><span class="cx">     static constexpr RegisterID framePointerRegister = X86Registers::ebp;
</span><span class="cx">     
</span><del>-    static bool canBlind() { return true; }
-    static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
-    static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
</del><ins>+    static bool constexpr canBlind() { return true; }
+    static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
+    static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
</ins><span class="cx"> 
</span><span class="cx">     // Integer arithmetic operations:
</span><span class="cx">     //
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeAccessCasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -486,7 +486,6 @@
</span><span class="cx">     case CustomAccessorGetter:
</span><span class="cx">     case CustomValueSetter:
</span><span class="cx">     case CustomAccessorSetter:
</span><del>-    case IntrinsicGetter:
</del><span class="cx">     case InHit:
</span><span class="cx">     case InMiss:
</span><span class="cx">     case CheckPrivateBrand:
</span><span class="lines">@@ -529,6 +528,8 @@
</span><span class="cx">     case IndexedTypedArrayUint32Store:
</span><span class="cx">     case IndexedTypedArrayFloat32Store:
</span><span class="cx">     case IndexedTypedArrayFloat64Store:
</span><ins>+    // Used by TypedArrayLength/TypedArrayByteOffset in the process of boxing their result as a double
+    case IntrinsicGetter:
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -1184,12 +1185,17 @@
</span><span class="cx"> 
</span><span class="cx">         GPRReg propertyGPR = state.u.propertyGPR;
</span><span class="cx"> 
</span><del>-        
</del><span class="cx">         jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR);
</span><span class="cx">         fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
</span><span class="cx"> 
</span><del>-        jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
-        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR));
</del><ins>+        CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength());
+        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
+#if USE(LARGE_TYPED_ARRAYS)
+        // The length is a size_t, so either 32 or 64 bits depending on the platform.
+        state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength));
+#else
+        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength));
+#endif
</ins><span class="cx"> 
</span><span class="cx">         auto allocator = state.makeDefaultScratchAllocator(scratchGPR);
</span><span class="cx">         GPRReg scratch2GPR = allocator.allocateScratchGPR();
</span><span class="lines">@@ -1197,9 +1203,13 @@
</span><span class="cx">         ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(
</span><span class="cx">             jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        jit.load64(addressOfLength, scratchGPR);
+#else
+        jit.load32(addressOfLength, scratchGPR);
+#endif
</ins><span class="cx">         jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
</span><span class="cx">         jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
</span><del>-
</del><span class="cx">         jit.signExtend32ToPtr(propertyGPR, scratchGPR);
</span><span class="cx">         if (isInt(type)) {
</span><span class="cx">             switch (elementSize(type)) {
</span><span class="lines">@@ -1595,9 +1605,14 @@
</span><span class="cx">             ready.link(&jit);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
-        // OutOfBounds bit of ArrayProfile will be set in the operation function.
-        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR));
</del><ins>+        CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength());
+        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
+#if USE(LARGE_TYPED_ARRAYS)
+        // The length is a UCPURegister, so either 32 or 64 bits depending on the platform.
+        state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength));
+#else
+        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength));
+#endif
</ins><span class="cx"> 
</span><span class="cx">         auto allocator = state.makeDefaultScratchAllocator(scratchGPR);
</span><span class="cx">         GPRReg scratch2GPR = allocator.allocateScratchGPR();
</span><span class="lines">@@ -1605,9 +1620,13 @@
</span><span class="cx">         ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(
</span><span class="cx">             jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        jit.load64(addressOfLength, scratchGPR);
+#else
+        jit.load32(addressOfLength, scratchGPR);
+#endif
</ins><span class="cx">         jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
</span><span class="cx">         jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
</span><del>-
</del><span class="cx">         jit.signExtend32ToPtr(propertyGPR, scratchGPR);
</span><span class="cx">         if (isInt(type)) {
</span><span class="cx">             if (isClamped(type)) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArrayProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> 
</span><span class="cx"> // This is a bitfield where each bit represents an type of array access that we have seen.
</span><span class="cx"> // There are 19 indexing types that use the lower bits.
</span><del>-// There are 9 typed array types taking the bits 16 to 25.
</del><ins>+// There are 11 typed array types taking the bits 16-20 and 26-31.
</ins><span class="cx"> typedef unsigned ArrayModes;
</span><span class="cx"> 
</span><span class="cx"> // The possible IndexingTypes are limited within (0 - 16, 21, 23, 25).
</span><span class="lines">@@ -205,7 +205,15 @@
</span><span class="cx">         , m_didPerformFirstRunPruning(false)
</span><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+#if USE(LARGE_TYPED_ARRAYS)
+    static constexpr uint64_t s_smallTypedArrayMaxLength = std::numeric_limits<int32_t>::max();
+    void setMayBeLargeTypedArray() { m_mayBeLargeTypedArray = true; }
+    bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return m_mayBeLargeTypedArray; }
+#else
+    bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return false; }
+#endif
+
</ins><span class="cx">     StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; }
</span><span class="cx">     ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
</span><span class="cx">     bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
</span><span class="lines">@@ -244,6 +252,9 @@
</span><span class="cx">     StructureID m_lastSeenStructureID { 0 };
</span><span class="cx">     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.
</span><span class="cx">     bool m_outOfBounds { false };
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    bool m_mayBeLargeTypedArray { false };
+#endif
</ins><span class="cx">     bool m_mayInterceptIndexedAccesses : 1;
</span><span class="cx">     bool m_usesOriginalArrayStructures : 1;
</span><span class="cx">     bool m_didPerformFirstRunPruning : 1;
</span><span class="lines">@@ -253,7 +264,13 @@
</span><span class="cx"> 
</span><span class="cx"> class UnlinkedArrayProfile {
</span><span class="cx"> public:
</span><del>-    UnlinkedArrayProfile() = default;
</del><ins>+    explicit UnlinkedArrayProfile()
+        : m_usesOriginalArrayStructures(true)
+#if USE(LARGE_TYPED_ARRAYS)
+        , m_mayBeLargeTypedArray(false)
+#endif
+    {
+    }
</ins><span class="cx"> 
</span><span class="cx">     void update(ArrayProfile& arrayProfile)
</span><span class="cx">     {
</span><span class="lines">@@ -280,6 +297,13 @@
</span><span class="cx">             arrayProfile.m_usesOriginalArrayStructures = false;
</span><span class="cx">         else
</span><span class="cx">             m_usesOriginalArrayStructures = arrayProfile.m_usesOriginalArrayStructures;
</span><ins>+
+#if USE(LARGE_TYPED_ARRAYS)
+        if (m_mayBeLargeTypedArray)
+            arrayProfile.m_mayBeLargeTypedArray = true;
+        else
+            m_mayBeLargeTypedArray = arrayProfile.m_mayBeLargeTypedArray;
+#endif
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -290,7 +314,11 @@
</span><span class="cx">     bool m_mayStoreToHole { false };
</span><span class="cx">     bool m_outOfBounds { false };
</span><span class="cx">     bool m_mayInterceptIndexedAccesses { false };
</span><del>-    bool m_usesOriginalArrayStructures { true };
</del><ins>+    bool m_usesOriginalArrayStructures : 1;
+#if USE(LARGE_TYPED_ARRAYS)
+    bool m_mayBeLargeTypedArray : 1;
+#endif
</ins><span class="cx"> };
</span><ins>+static_assert(sizeof(UnlinkedArrayProfile) <= 8);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -3463,7 +3463,7 @@
</span><span class="cx">     case GetArrayLength: {
</span><span class="cx">         JSArrayBufferView* view = m_graph.tryGetFoldableView(
</span><span class="cx">             forNode(node->child1()).m_value, node->arrayMode());
</span><del>-        if (view) {
</del><ins>+        if (view && isInBounds<int32_t>(view->length())) {
</ins><span class="cx">             setConstant(node, jsNumber(view->length()));
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -3471,6 +3471,17 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayLengthAsInt52: {
+        JSArrayBufferView* view = m_graph.tryGetFoldableView(
+            forNode(node->child1()).m_value, node->arrayMode());
+        if (view) {
+            setConstant(node, jsNumber(view->length()));
+            break;
+        }
+        setNonCellTypeForNode(node, SpecInt52Any);
+        break;
+    }
+
</ins><span class="cx">     case GetVectorLength: {
</span><span class="cx">         setNonCellTypeForNode(node, SpecInt32Only);
</span><span class="cx">         break;
</span><span class="lines">@@ -3796,8 +3807,8 @@
</span><span class="cx">     case GetTypedArrayByteOffset: {
</span><span class="cx">         JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
</span><span class="cx">         if (view) {
</span><del>-            std::optional<unsigned> byteOffset = view->byteOffsetConcurrently();
-            if (byteOffset) {
</del><ins>+            std::optional<size_t> byteOffset = view->byteOffsetConcurrently();
+            if (byteOffset && isInBounds<int32_t>(byteOffset)) {
</ins><span class="cx">                 setConstant(node, jsNumber(*byteOffset));
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -3806,6 +3817,19 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayByteOffsetAsInt52: {
+        JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
+        if (view) {
+            std::optional<size_t> byteOffset = view->byteOffsetConcurrently();
+            if (byteOffset) {
+                setConstant(node, jsNumber(*byteOffset));
+                break;
+            }
+        }
+        setNonCellTypeForNode(node, SpecInt52Any);
+        break;
+    }
+
</ins><span class="cx">     case GetPrototypeOf: {
</span><span class="cx">         AbstractValue& value = forNode(node->child1());
</span><span class="cx">         if ((value.m_type && !(value.m_type & ~SpecObject)) && value.m_structure.isFinite()) {
</span><span class="lines">@@ -4109,6 +4133,11 @@
</span><span class="cx">         setNonCellTypeForNode(node, SpecInt32Only);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+    case CheckInBoundsInt52: {
+        // See the CheckInBounds case, it does not really matter what we put here.
+        setNonCellTypeForNode(node, SpecInt32Only);
+        break;
+    }
</ins><span class="cx"> 
</span><span class="cx">     case CheckPrivateBrand:
</span><span class="cx">     case SetPrivateBrand:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -325,6 +325,11 @@
</span><span class="cx">                         escape(node->child1(), node);
</span><span class="cx">                     break;
</span><span class="cx"> 
</span><ins>+                case GetTypedArrayLengthAsInt52:
+                    // This node is only used for TypedArrays, so should not be relevant for arguments elimination
+                    escape(node->child2(), node);
+                    break;
+
</ins><span class="cx">                 case NewArrayWithSpread: {
</span><span class="cx">                     BitVector* bitVector = node->bitVector();
</span><span class="cx">                     bool isWatchingHavingABadTimeWatchpoint = m_graph.isWatchingHavingABadTimeWatchpoint(node); 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -209,7 +209,7 @@
</span><span class="cx">         return ArrayMode(Array::ForceExit, action());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (!isInt32Speculation(index))
</del><ins>+    if (!isInt32Speculation(index) && !mayBeLargeTypedArray())
</ins><span class="cx">         return ArrayMode(Array::Generic, action());
</span><span class="cx">     
</span><span class="cx">     // If we had exited because of an exotic object behavior, then don't try to specialize.
</span><span class="lines">@@ -294,6 +294,8 @@
</span><span class="cx">     case Array::Float64Array:
</span><span class="cx">     case Array::BigInt64Array:
</span><span class="cx">     case Array::BigUint64Array:
</span><ins>+        // FIXME: no idea why we only preserve this out-of-bounds information for PutByVal and not GetByVal as well.
+        // https://bugs.webkit.org/show_bug.cgi?id=231276
</ins><span class="cx">         if (node->op() == PutByVal) {
</span><span class="cx">             if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
</span><span class="cx">                 return typedArrayResult(withSpeculation(Array::OutOfBounds));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -127,6 +127,7 @@
</span><span class="cx">         u.asBytes.speculation = Array::InBounds;
</span><span class="cx">         u.asBytes.conversion = Array::AsIs;
</span><span class="cx">         u.asBytes.action = Array::Write;
</span><ins>+        u.asBytes.mayBeLargeTypedArray = false;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     explicit ArrayMode(Array::Type type, Array::Action action)
</span><span class="lines">@@ -136,6 +137,7 @@
</span><span class="cx">         u.asBytes.speculation = Array::InBounds;
</span><span class="cx">         u.asBytes.conversion = Array::AsIs;
</span><span class="cx">         u.asBytes.action = action;
</span><ins>+        u.asBytes.mayBeLargeTypedArray = false;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ArrayMode(Array::Type type, Array::Class arrayClass, Array::Action action)
</span><span class="lines">@@ -145,9 +147,10 @@
</span><span class="cx">         u.asBytes.speculation = Array::InBounds;
</span><span class="cx">         u.asBytes.conversion = Array::AsIs;
</span><span class="cx">         u.asBytes.action = action;
</span><ins>+        u.asBytes.mayBeLargeTypedArray = false;
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action)
</del><ins>+    ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action, bool mayBeLargeTypedArray = false)
</ins><span class="cx">     {
</span><span class="cx">         u.asBytes.type = type;
</span><span class="cx">         u.asBytes.arrayClass = arrayClass;
</span><span class="lines">@@ -154,6 +157,7 @@
</span><span class="cx">         u.asBytes.speculation = speculation;
</span><span class="cx">         u.asBytes.conversion = conversion;
</span><span class="cx">         u.asBytes.action = action;
</span><ins>+        u.asBytes.mayBeLargeTypedArray = mayBeLargeTypedArray;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ArrayMode(Array::Type type, Array::Class arrayClass, Array::Conversion conversion, Array::Action action)
</span><span class="lines">@@ -163,6 +167,7 @@
</span><span class="cx">         u.asBytes.speculation = Array::InBounds;
</span><span class="cx">         u.asBytes.conversion = conversion;
</span><span class="cx">         u.asBytes.action = action;
</span><ins>+        u.asBytes.mayBeLargeTypedArray = false;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Array::Type type() const { return static_cast<Array::Type>(u.asBytes.type); }
</span><span class="lines">@@ -170,6 +175,7 @@
</span><span class="cx">     Array::Speculation speculation() const { return static_cast<Array::Speculation>(u.asBytes.speculation); }
</span><span class="cx">     Array::Conversion conversion() const { return static_cast<Array::Conversion>(u.asBytes.conversion); }
</span><span class="cx">     Array::Action action() const { return static_cast<Array::Action>(u.asBytes.action); }
</span><ins>+    bool mayBeLargeTypedArray() const { return u.asBytes.mayBeLargeTypedArray; }
</ins><span class="cx">     
</span><span class="cx">     unsigned asWord() const { return u.asWord; }
</span><span class="cx">     
</span><span class="lines">@@ -179,35 +185,50 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     static ArrayMode fromObserved(const ConcurrentJSLocker&, ArrayProfile*, Array::Action, bool makeSafe);
</span><del>-    
</del><ins>+
+    ArrayMode withType(Array::Type type) const
+    {
+        return ArrayMode(type, arrayClass(), speculation(), conversion(), action(), mayBeLargeTypedArray());
+    }
+
</ins><span class="cx">     ArrayMode withSpeculation(Array::Speculation speculation) const
</span><span class="cx">     {
</span><del>-        return ArrayMode(type(), arrayClass(), speculation, conversion(), action());
</del><ins>+        return ArrayMode(type(), arrayClass(), speculation, conversion(), action(), mayBeLargeTypedArray());
</ins><span class="cx">     }
</span><del>-    
-    ArrayMode withArrayClass(Array::Class arrayClass) const
</del><ins>+
+    ArrayMode withConversion(Array::Conversion conversion) const
</ins><span class="cx">     {
</span><del>-        return ArrayMode(type(), arrayClass, speculation(), conversion(), action());
</del><ins>+        return ArrayMode(type(), arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray());
</ins><span class="cx">     }
</span><del>-    
-    ArrayMode withSpeculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
</del><ins>+
+    ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const
</ins><span class="cx">     {
</span><del>-        Array::Speculation mySpeculation;
</del><ins>+        return ArrayMode(type, arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray());
+    }
</ins><span class="cx"> 
</span><ins>+    ArrayMode withArrayClassAndSpeculationAndMayBeLargeTypedArray(Array::Class arrayClass, Array::Speculation speculation, bool mayBeLargeTypedArray) const
+    {
+        return ArrayMode(type(), arrayClass, speculation, conversion(), action(), mayBeLargeTypedArray);
+    }
+
+    static Array::Speculation speculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe)
+    {
</ins><span class="cx">         if (makeSafe)
</span><del>-            mySpeculation = Array::OutOfBounds;
</del><ins>+            return Array::OutOfBounds;
</ins><span class="cx">         else if (profile->mayStoreToHole(locker))
</span><del>-            mySpeculation = Array::ToHole;
</del><ins>+            return Array::ToHole;
</ins><span class="cx">         else
</span><del>-            mySpeculation = Array::InBounds;
-        
-        return withSpeculation(mySpeculation);
</del><ins>+            return Array::InBounds;
</ins><span class="cx">     }
</span><del>-    
</del><ins>+
+    ArrayMode withSpeculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
+    {
+        return withSpeculation(speculationFromProfile(locker, profile, makeSafe));
+    }
+
</ins><span class="cx">     ArrayMode withProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const
</span><span class="cx">     {
</span><span class="cx">         Array::Class myArrayClass;
</span><del>-
</del><span class="cx">         if (isJSArray()) {
</span><span class="cx">             if (profile->usesOriginalArrayStructures(locker) && benefitsFromOriginalArray()) {
</span><span class="cx">                 ArrayModes arrayModes = profile->observedArrayModes(locker);
</span><span class="lines">@@ -221,25 +242,14 @@
</span><span class="cx">                 myArrayClass = Array::Array;
</span><span class="cx">         } else
</span><span class="cx">             myArrayClass = arrayClass();
</span><del>-        
-        return withArrayClass(myArrayClass).withSpeculationFromProfile(locker, profile, makeSafe);
</del><ins>+
+        Array::Speculation speculation = speculationFromProfile(locker, profile, makeSafe);
+
+        bool largeTypedArray = profile->mayBeLargeTypedArray(locker);
+
+        return withArrayClassAndSpeculationAndMayBeLargeTypedArray(myArrayClass, speculation, largeTypedArray);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    ArrayMode withType(Array::Type type) const
-    {
-        return ArrayMode(type, arrayClass(), speculation(), conversion(), action());
-    }
-    
-    ArrayMode withConversion(Array::Conversion conversion) const
-    {
-        return ArrayMode(type(), arrayClass(), speculation(), conversion, action());
-    }
-    
-    ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const
-    {
-        return ArrayMode(type, arrayClass(), speculation(), conversion, action());
-    }
-    
</del><span class="cx">     static constexpr SpeculatedType unusedIndexSpeculatedType = SpecInt32Only;
</span><span class="cx">     ArrayMode refine(Graph&, Node*, SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone) const;
</span><span class="cx">     
</span><span class="lines">@@ -526,7 +536,8 @@
</span><span class="cx">         return type() == other.type()
</span><span class="cx">             && arrayClass() == other.arrayClass()
</span><span class="cx">             && speculation() == other.speculation()
</span><del>-            && conversion() == other.conversion();
</del><ins>+            && conversion() == other.conversion()
+            && mayBeLargeTypedArray() == other.mayBeLargeTypedArray();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool operator!=(const ArrayMode& other) const
</span><span class="lines">@@ -579,7 +590,8 @@
</span><span class="cx">             uint8_t arrayClass;
</span><span class="cx">             uint8_t speculation;
</span><span class="cx">             uint8_t conversion : 4;
</span><del>-            uint8_t action : 4;
</del><ins>+            uint8_t action : 1;
+            uint8_t mayBeLargeTypedArray : 1;
</ins><span class="cx">         } asBytes;
</span><span class="cx">         unsigned asWord;
</span><span class="cx">     } u;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -3807,8 +3807,17 @@
</span><span class="cx"> template<typename ChecksFunctor>
</span><span class="cx"> bool ByteCodeParser::handleIntrinsicGetter(Operand result, SpeculatedType prediction, const GetByVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
</span><span class="cx"> {
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    static_assert(enableInt52());
+#endif
+
</ins><span class="cx">     switch (variant.intrinsic()) {
</span><span class="cx">     case TypedArrayByteLengthIntrinsic: {
</span><ins>+        bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
+#if !USE(LARGE_TYPED_ARRAYS)
+        if (willNeedGetTypedArrayLengthAsInt52)
+            return false;
+#endif
</ins><span class="cx">         insertChecks();
</span><span class="cx"> 
</span><span class="cx">         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
</span><span class="lines">@@ -3822,26 +3831,30 @@
</span><span class="cx">             ASSERT(arrayType != Array::Generic);
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
</del><ins>+        NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength;
+        Node* lengthNode = addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
</ins><span class="cx">         // Our ArrayMode shouldn't cause us to exit here so we should be ok to exit without effects.
</span><span class="cx">         m_exitOK = true;
</span><span class="cx">         addToGraph(ExitOK);
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         if (!logSize) {
</span><span class="cx">             set(result, lengthNode);
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // We can use a BitLShift here because typed arrays will never have a byteLength
-        // that overflows int32.
-        Node* shiftNode = jsConstant(jsNumber(logSize));
-        set(result, addToGraph(ArithBitLShift, lengthNode, shiftNode));
</del><ins>+        // We cannot use a BitLShift here because typed arrays may have a byteLength that overflows Int32.
+        Node* typeSize = jsConstant(jsNumber(1 << logSize));
+        set(result, addToGraph(ArithMul, lengthNode, typeSize));
</ins><span class="cx"> 
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case TypedArrayLengthIntrinsic: {
</span><ins>+        bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
+#if !USE(LARGE_TYPED_ARRAYS)
+        if (willNeedGetTypedArrayLengthAsInt52)
+            return false;
+#endif
</ins><span class="cx">         insertChecks();
</span><span class="cx"> 
</span><span class="cx">         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
</span><span class="lines">@@ -3853,7 +3866,8 @@
</span><span class="cx">             ASSERT(arrayType != Array::Generic);
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        set(result, addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
</del><ins>+        NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength;
+        set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
</ins><span class="cx"> 
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="lines">@@ -3860,6 +3874,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case TypedArrayByteOffsetIntrinsic: {
</span><ins>+        bool willNeedGetTypedArrayByteOffsetAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow);
+#if !USE(LARGE_TYPED_ARRAYS)
+        if (willNeedGetTypedArrayByteOffsetAsInt52)
+            return false;
+#endif
</ins><span class="cx">         insertChecks();
</span><span class="cx"> 
</span><span class="cx">         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
</span><span class="lines">@@ -3871,7 +3890,8 @@
</span><span class="cx">             ASSERT(arrayType != Array::Generic);
</span><span class="cx">         });
</span><span class="cx"> 
</span><del>-        set(result, addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
</del><ins>+        NodeType op = willNeedGetTypedArrayByteOffsetAsInt52 ? GetTypedArrayByteOffsetAsInt52 : GetTypedArrayByteOffset;
+        set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
</ins><span class="cx"> 
</span><span class="cx">         return true;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -153,6 +153,7 @@
</span><span class="cx">         case EnumeratorHasOwnProperty:
</span><span class="cx">         case GetIndexedPropertyStorage:
</span><span class="cx">         case GetArrayLength:
</span><ins>+        case GetTypedArrayLengthAsInt52:
</ins><span class="cx">         case GetVectorLength:
</span><span class="cx">         case InByVal:
</span><span class="cx">         case PutByValDirect:
</span><span class="lines">@@ -239,6 +240,7 @@
</span><span class="cx">     case ToBoolean:
</span><span class="cx">     case LogicalNot:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case DoubleRep:
</span><span class="cx">     case ValueRep:
</span><span class="cx">     case Int52Rep:
</span><span class="lines">@@ -1337,6 +1339,11 @@
</span><span class="cx">         def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), LazyNode(node));
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayByteOffsetAsInt52:
+        read(MiscFields);
+        def(HeapLocation(TypedArrayByteOffsetInt52Loc, MiscFields, node->child1()), LazyNode(node));
+        return;
+
</ins><span class="cx">     case GetPrototypeOf: {
</span><span class="cx">         switch (node->child1().useKind()) {
</span><span class="cx">         case ArrayUse:
</span><span class="lines">@@ -1444,6 +1451,14 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayLengthAsInt52: {
+        ArrayMode mode = node->arrayMode();
+        RELEASE_ASSERT(mode.isSomeTypedArrayView());
+        read(MiscFields);
+        def(HeapLocation(TypedArrayLengthInt52Loc, MiscFields, node->child1()), LazyNode(node));
+        return;
+    }
+
</ins><span class="cx">     case GetVectorLength: {
</span><span class="cx">         ArrayMode mode = node->arrayMode();
</span><span class="cx">         switch (mode.type()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -92,7 +92,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool enableInt52()
</del><ins>+inline bool constexpr enableInt52()
</ins><span class="cx"> {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     return true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -387,6 +387,8 @@
</span><span class="cx">                 
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+            case CheckInBoundsInt52:
+                break;
</ins><span class="cx">                 
</span><span class="cx">             case GetMyArgumentByVal:
</span><span class="cx">             case GetMyArgumentByValOutOfBounds: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx">     case NotifyWrite:
</span><span class="cx">     case AssertInBounds:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><span class="cx">     case CheckVarargs:
</span><span class="lines">@@ -197,10 +198,12 @@
</span><span class="cx">     case GetGetter:
</span><span class="cx">     case GetSetter:
</span><span class="cx">     case GetArrayLength:
</span><ins>+    case GetTypedArrayLengthAsInt52:
</ins><span class="cx">     case GetVectorLength:
</span><span class="cx">     case StringCharCodeAt:
</span><span class="cx">     case StringCodePointAt:
</span><span class="cx">     case GetTypedArrayByteOffset:
</span><ins>+    case GetTypedArrayByteOffsetAsInt52:
</ins><span class="cx">     case GetPrototypeOf:
</span><span class="cx">     case PutStructure:
</span><span class="cx">     case GetByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1043,6 +1043,7 @@
</span><span class="cx">                     && isFullNumberSpeculation(indexSpeculation)
</span><span class="cx">                     && node->arrayMode().isSpecific()
</span><span class="cx">                     && node->arrayMode().isInBounds()
</span><ins>+                    && !node->arrayMode().mayBeLargeTypedArray()
</ins><span class="cx">                     && !m_graph.hasExitSite(node->origin.semantic, Overflow)) {
</span><span class="cx"> 
</span><span class="cx">                     Node* newIndex = m_insertionSet.insertNode(
</span><span class="lines">@@ -1073,7 +1074,7 @@
</span><span class="cx"> 
</span><span class="cx">             case Array::ForceExit: {
</span><span class="cx">                 // Don't force OSR because we have only seen OwnStructureMode.
</span><del>-                // FIXME: WE should have a better way to do this...
</del><ins>+                // FIXME: We should have a better way to do this...
</ins><span class="cx">                 if (node->op() == EnumeratorGetByVal)
</span><span class="cx">                     node->setArrayMode(node->arrayMode().withType(Array::Generic));
</span><span class="cx">                 break;
</span><span class="lines">@@ -1133,6 +1134,18 @@
</span><span class="cx">                 fixEdge<KnownStringUse>(m_graph.varArgChild(node, 0));
</span><span class="cx">                 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
</span><span class="cx">                 break;
</span><ins>+            case Array::Int8Array:
+            case Array::Int16Array:
+            case Array::Int32Array:
+            case Array::Uint8Array:
+            case Array::Uint8ClampedArray:
+            case Array::Uint16Array:
+            case Array::Uint32Array:
+            case Array::Float32Array:
+            case Array::Float64Array:
+                fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
+                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
+                break;
</ins><span class="cx">             default:
</span><span class="cx">                 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
</span><span class="cx">                 fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
</span><span class="lines">@@ -1184,6 +1197,7 @@
</span><span class="cx">                     && isFullNumberSpeculation(indexSpeculation)
</span><span class="cx">                     && node->arrayMode().isSpecific()
</span><span class="cx">                     && node->arrayMode().isInBounds()
</span><ins>+                    && !node->arrayMode().mayBeLargeTypedArray()
</ins><span class="cx">                     && !m_graph.hasExitSite(node->origin.semantic, Overflow)) {
</span><span class="cx"> 
</span><span class="cx">                     Node* newIndex = m_insertionSet.insertNode(
</span><span class="lines">@@ -1717,12 +1731,16 @@
</span><span class="cx">             
</span><span class="cx">         case NewTypedArray: {
</span><span class="cx">             watchHavingABadTime(node);
</span><del>-            
</del><span class="cx">             if (node->child1()->shouldSpeculateInt32()) {
</span><span class="cx">                 fixEdge<Int32Use>(node->child1());
</span><span class="cx">                 node->clearFlags(NodeMustGenerate);
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+            if (node->child1()->shouldSpeculateInt52()) {
+                fixEdge<Int52RepUse>(node->child1());
+                node->clearFlags(NodeMustGenerate);
+                break;
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -2149,6 +2167,23 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case GetTypedArrayLengthAsInt52: {
+            ArrayMode arrayMode = node->arrayMode().refine(m_graph, node, node->child1()->prediction(), ArrayMode::unusedIndexSpeculatedType);
+            ASSERT(arrayMode.isSomeTypedArrayView());
+            node->setArrayMode(arrayMode);
+            blessArrayOperation(node->child1(), Edge(), node->child2(), lengthNeedsStorage);
+
+            fixEdge<KnownCellUse>(node->child1());
+            node->setResult(NodeResultInt52);
+            break;
+        }
+
+        case GetTypedArrayByteOffsetAsInt52: {
+            fixEdge<KnownCellUse>(node->child1());
+            node->setResult(NodeResultInt52);
+            break;
+        }
+
</ins><span class="cx">         case GetTypedArrayByteOffset: {
</span><span class="cx">             fixEdge<KnownCellUse>(node->child1());
</span><span class="cx">             break;
</span><span class="lines">@@ -2182,6 +2217,7 @@
</span><span class="cx">         case CheckTierUpAndOSREnter:
</span><span class="cx">         case AssertInBounds:
</span><span class="cx">         case CheckInBounds:
</span><ins>+        case CheckInBoundsInt52:
</ins><span class="cx">         case ConstantStoragePointer:
</span><span class="cx">         case DoubleAsInt32:
</span><span class="cx">         case ValueToInt32:
</span><span class="lines">@@ -4096,14 +4132,6 @@
</span><span class="cx">             
</span><span class="cx">         node->child2() = Edge(storage);
</span><span class="cx">     }
</span><del>-    
-    Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
-    {
-        Node* storage = checkArray(arrayMode, origin, child, nullptr, lengthNeedsStorage);
-        return m_insertionSet.insertNode(
-            m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
-            OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
-    }
</del><span class="cx"> 
</span><span class="cx">     void convertToHasIndexedProperty(Node* node)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGenerationInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -39,8 +39,7 @@
</span><span class="cx"> // This class is used to track the current status of live values during code generation.
</span><span class="cx"> // Can provide information as to whether a value is in machine registers, and if so which,
</span><span class="cx"> // whether a value has been spilled to the RegisterFile, and if so may be able to provide
</span><del>-// details of the format in memory (all values are spilled in a boxed form, but we may be
-// able to track the type of box), and tracks how many outstanding uses of a value remain,
</del><ins>+// details of the format in memory, and tracks how many outstanding uses of a value remain,
</ins><span class="cx"> // so that we know when the value is dead and the machine registers associated with it
</span><span class="cx"> // may be released.
</span><span class="cx"> class GenerationInfo {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -182,6 +182,14 @@
</span><span class="cx">         out.print("TypedArrayByteOffsetLoc");
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    case TypedArrayByteOffsetInt52Loc:
+        out.print("TypedArrayByteOffsetInt52Loc");
+        return;
+
+    case TypedArrayLengthInt52Loc:
+        out.print("TypedArrayLengthInt52Loc");
+        return;
+
</ins><span class="cx">     case PrototypeLoc:
</span><span class="cx">         out.print("PrototypeLoc");
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGHeapLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -67,6 +67,8 @@
</span><span class="cx">     SetterLoc,
</span><span class="cx">     StructureLoc,
</span><span class="cx">     TypedArrayByteOffsetLoc,
</span><ins>+    TypedArrayByteOffsetInt52Loc,
+    TypedArrayLengthInt52Loc,
</ins><span class="cx">     PrototypeLoc,
</span><span class="cx">     StackLoc,
</span><span class="cx">     StackPayloadLoc,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1335,7 +1335,7 @@
</span><span class="cx">                     
</span><span class="cx">                     if (nonNegative && lessThanLength) {
</span><span class="cx">                         executeNode(block->at(nodeIndex));
</span><del>-                        if (UNLIKELY(Options::validateBoundsCheckElimination()))
</del><ins>+                        if (UNLIKELY(Options::validateBoundsCheckElimination()) && node->op() == CheckInBounds)
</ins><span class="cx">                             m_insertionSet.insertNode(nodeIndex, SpecNone, AssertInBounds, node->origin, node->child1(), node->child2());
</span><span class="cx">                         // We just need to make sure we are a value-producing node.
</span><span class="cx">                         node->convertToIdentityOn(node->child1().node());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1965,6 +1965,7 @@
</span><span class="cx">         case ArrayPush:
</span><span class="cx">         case ArrayPop:
</span><span class="cx">         case GetArrayLength:
</span><ins>+        case GetTypedArrayLengthAsInt52:
</ins><span class="cx">         case HasIndexedProperty:
</span><span class="cx">         case EnumeratorNextUpdateIndexAndMode:
</span><span class="cx">         case ArrayIndexOf:
</span><span class="lines">@@ -2004,6 +2005,7 @@
</span><span class="cx"> 
</span><span class="cx">         case ArrayPop:
</span><span class="cx">         case GetArrayLength:
</span><ins>+        case GetTypedArrayLengthAsInt52:
</ins><span class="cx">             return 2;
</span><span class="cx"> 
</span><span class="cx">         case HasIndexedProperty:
</span><span class="lines">@@ -2276,6 +2278,7 @@
</span><span class="cx">         switch (op()) {
</span><span class="cx">         case GetIndexedPropertyStorage:
</span><span class="cx">         case GetArrayLength:
</span><ins>+        case GetTypedArrayLengthAsInt52:
</ins><span class="cx">         case GetVectorLength:
</span><span class="cx">         case InByVal:
</span><span class="cx">         case PutByValDirect:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -261,8 +261,12 @@
</span><span class="cx">     macro(MultiPutByOffset, NodeMustGenerate) \
</span><span class="cx">     macro(MultiDeleteByOffset, NodeMustGenerate | NodeResultJS) \
</span><span class="cx">     macro(GetArrayLength, NodeResultInt32) \
</span><ins>+    /* This is only relevant for TypedArrays, as they are the only ones that can have a length that does not fit in 32 bits. */ \
+    /* GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 change to returning Int52 in Fixup. Doing it before causes validation failures. */ \
+    macro(GetTypedArrayLengthAsInt52, NodeResultJS) \
</ins><span class="cx">     macro(GetVectorLength, NodeResultInt32) \
</span><span class="cx">     macro(GetTypedArrayByteOffset, NodeResultInt32) \
</span><ins>+    macro(GetTypedArrayByteOffsetAsInt52, NodeResultJS) \
</ins><span class="cx">     macro(GetScope, NodeResultJS) \
</span><span class="cx">     macro(SkipScope, NodeResultJS) \
</span><span class="cx">     macro(ResolveScope, NodeResultJS | NodeMustGenerate) \
</span><span class="lines">@@ -286,6 +290,7 @@
</span><span class="cx">     macro(CheckBadValue, NodeMustGenerate) \
</span><span class="cx">     macro(AssertInBounds, NodeMustGenerate) \
</span><span class="cx">     macro(CheckInBounds, NodeMustGenerate | NodeResultJS) \
</span><ins>+    macro(CheckInBoundsInt52, NodeMustGenerate | NodeResultJS) \
</ins><span class="cx">     macro(CheckIdent, NodeMustGenerate) \
</span><span class="cx">     macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
</span><span class="cx">     macro(CheckJSCast, NodeMustGenerate) /* This is the same as jsCast but as a speculation rather than assertion */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -97,10 +97,8 @@
</span><span class="cx">     }
</span><span class="cx">     if (baseValue.isObject()) {
</span><span class="cx">         JSObject* object = asObject(baseValue);
</span><del>-        if (object->canSetIndexQuickly(index, value)) {
-            object->setIndexQuickly(vm, index, value);
</del><ins>+        if (object->trySetIndexQuickly(vm, index, value))
</ins><span class="cx">             return;
</span><del>-        }
</del><span class="cx"> 
</span><span class="cx">         object->methodTable(vm)->putByIndex(object, globalObject, index, value, strict);
</span><span class="cx">         return;
</span><span class="lines">@@ -175,7 +173,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename ViewClass>
</span><del>-char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, int32_t size, char* vector)
</del><ins>+char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, intptr_t size, char* vector)
</ins><span class="cx"> {
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx"> 
</span><span class="lines">@@ -183,11 +181,14 @@
</span><span class="cx">         throwException(globalObject, scope, createRangeError(globalObject, "Requested length is negative"_s));
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    static_assert(std::numeric_limits<intptr_t>::max() <= std::numeric_limits<size_t>::max());
+    size_t unsignedSize = static_cast<size_t>(size);
+
</ins><span class="cx">     if (vector)
</span><del>-        return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, size, untagArrayPtr(vector, size)));
</del><ins>+        return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, unsignedSize, untagArrayPtr(vector, unsignedSize)));
</ins><span class="cx"> 
</span><del>-    RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, size)));
</del><ins>+    RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, unsignedSize)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template <bool strict>
</span><span class="lines">@@ -1908,7 +1909,7 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -1924,7 +1925,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -1940,7 +1941,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -1956,7 +1957,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -1972,7 +1973,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -1988,7 +1989,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2004,7 +2005,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2020,7 +2021,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2036,7 +2037,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2052,7 +2053,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span><span class="lines">@@ -2068,7 +2069,7 @@
</span><span class="cx">     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSBigInt64Array>(globalObject, structure, encodedValue, 0, std::nullopt));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector))
</del><ins>+JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector))
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -119,27 +119,27 @@
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewEmptyArray, char*, (VM*, Structure*));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, Butterfly*));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSizeAndHint, char*, (JSGlobalObject*, Structure*, int32_t, int32_t, Butterfly*));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><del>-JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, char*));
</del><ins>+JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*));
</ins><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewArrayIterator, JSCell*, (VM*, Structure*));
</span><span class="cx"> JSC_DECLARE_JIT_OPERATION(operationNewMapIterator, JSCell*, (VM*, Structure*));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -986,6 +986,12 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case GetTypedArrayLengthAsInt52:
+        case GetTypedArrayByteOffsetAsInt52: {
+            setPrediction(SpecInt52Any);
+            break;
+        }
+
</ins><span class="cx">         case StringCharCodeAt:
</span><span class="cx">         case StringCodePointAt: {
</span><span class="cx">             setPrediction(SpecInt32Only);
</span><span class="lines">@@ -1320,6 +1326,7 @@
</span><span class="cx">         case CheckTierUpAndOSREnter:
</span><span class="cx">         case AssertInBounds:
</span><span class="cx">         case CheckInBounds:
</span><ins>+        case CheckInBoundsInt52:
</ins><span class="cx">         case ValueToInt32:
</span><span class="cx">         case DoubleRep:
</span><span class="cx">         case ValueRep:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSSALoweringPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -100,11 +100,21 @@
</span><span class="cx">                 break;
</span><span class="cx">             
</span><span class="cx">             if (m_node->arrayMode().typedArrayType() != NotTypedArray && m_node->arrayMode().isOutOfBounds()) {
</span><del>-                Node* length = m_insertionSet.insertNode(
-                    m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin,
-                    OpInfo(m_node->arrayMode().asWord()), base, storage);
-                
-                m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use);
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+                if (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow)) {
+                    Node* length = m_insertionSet.insertNode(
+                        m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin,
+                        OpInfo(m_node->arrayMode().asWord()), base, storage);
+                    m_graph.varArgChild(m_node, 4) = Edge(length, Int52RepUse);
+                } else {
+#endif
+                    Node* length = m_insertionSet.insertNode(
+                        m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin,
+                        OpInfo(m_node->arrayMode().asWord()), base, storage);
+                    m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use);
+#if USE(LARGE_TYPED_ARRAYS)
+                }
+#endif
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -137,13 +147,30 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        Node* length = m_insertionSet.insertNode(
-            m_nodeIndex, SpecInt32Only, op, m_node->origin,
-            OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
-        Node* checkInBounds = m_insertionSet.insertNode(
-            m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin,
-            index, Edge(length, KnownInt32Use));
</del><ins>+        Node* checkInBounds;
+#if USE(LARGE_TYPED_ARRAYS)
+        if ((op == GetArrayLength) && (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow))) {
+            Node* length = m_insertionSet.insertNode(
+                m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin,
+                OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
+            length->setResult(NodeResultInt52);
+            // The return type is a dummy since this node does not actually return anything.
+            checkInBounds = m_insertionSet.insertNode(
+                m_nodeIndex, SpecInt32Only, CheckInBoundsInt52, m_node->origin,
+                index, Edge(length, Int52RepUse));
+        } else {
+#endif
+            Node* length = m_insertionSet.insertNode(
+                m_nodeIndex, SpecInt32Only, op, m_node->origin,
+                OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage);
+            checkInBounds = m_insertionSet.insertNode(
+                m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin,
+                index, Edge(length, KnownInt32Use));
+#if USE(LARGE_TYPED_ARRAYS)
+        }
+#endif
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">         AdjacencyList adjacencyList = m_graph.copyVarargChildren(m_node);
</span><span class="cx">         m_graph.m_varArgChildren.append(Edge(checkInBounds, UntypedUse));
</span><span class="cx">         adjacencyList.setNumChildren(adjacencyList.numChildren() + 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -288,6 +288,7 @@
</span><span class="cx">     case ExtractCatchLocal:
</span><span class="cx">     case AssertInBounds:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><span class="cx">     case CheckVarargs:
</span><span class="lines">@@ -373,6 +374,7 @@
</span><span class="cx">     case GetByVal:
</span><span class="cx">     case GetIndexedPropertyStorage:
</span><span class="cx">     case GetArrayLength:
</span><ins>+    case GetTypedArrayLengthAsInt52:
</ins><span class="cx">     case GetVectorLength:
</span><span class="cx">     case ArrayPop:
</span><span class="cx">     case StringCharAt:
</span><span class="lines">@@ -385,6 +387,7 @@
</span><span class="cx"> 
</span><span class="cx">     case CheckDetached:
</span><span class="cx">     case GetTypedArrayByteOffset:
</span><ins>+    case GetTypedArrayByteOffsetAsInt52:
</ins><span class="cx">         return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView));
</span><span class="cx">             
</span><span class="cx">     case PutByValDirect:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -3238,7 +3238,7 @@
</span><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR)
</del><ins>+JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR)
</ins><span class="cx"> {
</span><span class="cx">     if (node->op() == PutByValAlias)
</span><span class="cx">         return JITCompiler::Jump();
</span><span class="lines">@@ -3245,21 +3245,36 @@
</span><span class="cx">     JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(
</span><span class="cx">         m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode());
</span><span class="cx">     if (view) {
</span><del>-        uint32_t length = view->length();
</del><ins>+        size_t length = view->length();
</ins><span class="cx">         Node* indexNode = m_jit.graph().child(node, 1).node();
</span><del>-        if (indexNode->isInt32Constant() && indexNode->asUInt32() < length)
</del><ins>+        if (indexNode->isAnyIntConstant() && indexNode->asUInt32() < length)
</ins><span class="cx">             return JITCompiler::Jump();
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        m_jit.signExtend32ToPtr(indexGPR, scratchGPR);
+        return m_jit.branch64(
+            MacroAssembler::AboveOrEqual, scratchGPR, MacroAssembler::Imm64(length));
+#else
+        UNUSED_PARAM(scratchGPR);
</ins><span class="cx">         return m_jit.branch32(
</span><span class="cx">             MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length));
</span><ins>+#endif
</ins><span class="cx">     }
</span><ins>+
+#if USE(LARGE_TYPED_ARRAYS)
+    m_jit.signExtend32ToPtr(indexGPR, scratchGPR);
+    return m_jit.branch64(
+        MacroAssembler::AboveOrEqual, scratchGPR,
+        MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
+#else
</ins><span class="cx">     return m_jit.branch32(
</span><span class="cx">         MacroAssembler::AboveOrEqual, indexGPR,
</span><span class="cx">         MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR)
</del><ins>+void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR)
</ins><span class="cx"> {
</span><del>-    JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR);
</del><ins>+    JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR, scratchGPR);
</ins><span class="cx">     if (!jump.isSet())
</span><span class="cx">         return;
</span><span class="cx">     speculationCheck(OutOfBounds, JSValueRegs(), nullptr, jump);
</span><span class="lines">@@ -3380,10 +3395,12 @@
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
</span><span class="cx">     StorageOperand storage(this, m_graph.varArgChild(node, 2));
</span><ins>+    GPRTemporary scratch(this);
</ins><span class="cx"> 
</span><span class="cx">     GPRReg baseReg = base.gpr();
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><span class="cx">     GPRReg storageReg = storage.gpr();
</span><ins>+    GPRReg scratchGPR = scratch.gpr();
</ins><span class="cx"> 
</span><span class="cx">     std::optional<FPRTemporary> fprTemp;
</span><span class="cx">     FPRReg resultFPR = InvalidFPRReg;
</span><span class="lines">@@ -3397,7 +3414,7 @@
</span><span class="cx">     std::tie(resultRegs, format) = prefix(DataFormatInt32);
</span><span class="cx">     bool shouldBox = format == DataFormatJS;
</span><span class="cx"> 
</span><del>-    emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
</del><ins>+    emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR);
</ins><span class="cx">     loadFromIntTypedArray(storageReg, propertyReg, resultRegs.payloadGPR(), type);
</span><span class="cx">     constexpr bool canSpeculate = true;
</span><span class="cx">     setIntTypedArrayLoadResult(node, resultRegs, type, canSpeculate, shouldBox, resultFPR);
</span><span class="lines">@@ -3555,6 +3572,7 @@
</span><span class="cx">     ASSERT(isInt(type));
</span><span class="cx">     
</span><span class="cx">     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
</span><ins>+    GPRTemporary scratch(this);
</ins><span class="cx">     GPRReg storageReg = storage.gpr();
</span><span class="cx">     
</span><span class="cx">     Edge valueUse = m_jit.graph().varArgChild(node, 2);
</span><span class="lines">@@ -3587,7 +3605,7 @@
</span><span class="cx">     ASSERT_UNUSED(valueGPR, valueGPR != property);
</span><span class="cx">     ASSERT(valueGPR != base);
</span><span class="cx">     ASSERT(valueGPR != storageReg);
</span><del>-    JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
</del><ins>+    JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratch.gpr());
</ins><span class="cx"> 
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 1:
</span><span class="lines">@@ -3645,10 +3663,12 @@
</span><span class="cx">     SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
</span><span class="cx">     SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
</span><span class="cx">     StorageOperand storage(this, m_graph.varArgChild(node, 2));
</span><ins>+    GPRTemporary scratch(this);
</ins><span class="cx"> 
</span><span class="cx">     GPRReg baseReg = base.gpr();
</span><span class="cx">     GPRReg propertyReg = property.gpr();
</span><span class="cx">     GPRReg storageReg = storage.gpr();
</span><ins>+    GPRReg scratchGPR = scratch.gpr();
</ins><span class="cx"> 
</span><span class="cx">     JSValueRegs resultRegs;
</span><span class="cx">     DataFormat format;
</span><span class="lines">@@ -3656,7 +3676,7 @@
</span><span class="cx"> 
</span><span class="cx">     FPRTemporary result(this);
</span><span class="cx">     FPRReg resultReg = result.fpr();
</span><del>-    emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
</del><ins>+    emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR);
</ins><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 4:
</span><span class="cx">         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
</span><span class="lines">@@ -3690,10 +3710,12 @@
</span><span class="cx"> 
</span><span class="cx">     SpeculateDoubleOperand valueOp(this, valueUse);
</span><span class="cx">     FPRTemporary scratch(this);
</span><ins>+    GPRTemporary gpScratch(this);
</ins><span class="cx">     FPRReg valueFPR = valueOp.fpr();
</span><span class="cx">     FPRReg scratchFPR = scratch.fpr();
</span><ins>+    GPRReg scratchGPR = gpScratch.gpr();
</ins><span class="cx"> 
</span><del>-    MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
</del><ins>+    MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratchGPR);
</ins><span class="cx">     
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 4: {
</span><span class="lines">@@ -7967,7 +7989,7 @@
</span><span class="cx"> {
</span><span class="cx">     auto untagArrayPtr = [&]() {
</span><span class="cx"> #if CPU(ARM64E)
</span><del>-        m_jit.untagArrayPtrLength32(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth);
</del><ins>+        m_jit.untagArrayPtrLength64(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth);
</ins><span class="cx"> #else
</span><span class="cx">         UNUSED_PARAM(validateAuth);
</span><span class="cx">         UNUSED_PARAM(baseReg);
</span><span class="lines">@@ -8039,9 +8061,6 @@
</span><span class="cx">     GPRReg baseGPR = base.gpr();
</span><span class="cx">     GPRReg vectorGPR = vector.gpr();
</span><span class="cx">     GPRReg dataGPR = data.gpr();
</span><del>-    ASSERT(baseGPR != vectorGPR);
-    ASSERT(baseGPR != dataGPR);
-    ASSERT(vectorGPR != dataGPR);
</del><span class="cx"> 
</span><span class="cx">     GPRReg arrayBufferGPR = dataGPR;
</span><span class="cx"> 
</span><span class="lines">@@ -8083,6 +8102,11 @@
</span><span class="cx">     nullVector.link(&m_jit);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
+    speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::Above, vectorGPR, TrustedImm32(std::numeric_limits<int32_t>::max())));
+#endif
+
</ins><span class="cx">     strictInt32Result(vectorGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -8349,12 +8373,18 @@
</span><span class="cx">         GPRTemporary result(this, Reuse, base);
</span><span class="cx">         GPRReg baseGPR = base.gpr();
</span><span class="cx">         GPRReg resultGPR = result.gpr();
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
+        speculationCheck(Overflow, JSValueSource(), nullptr, m_jit.branch64(MacroAssembler::Above, resultGPR, TrustedImm64(std::numeric_limits<int32_t>::max())));
+#else
</ins><span class="cx">         m_jit.load32(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
</span><ins>+#endif
</ins><span class="cx">         strictInt32Result(resultGPR, node);
</span><span class="cx">         break;
</span><span class="cx">     } }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> void SpeculativeJIT::compileCheckIdent(Node* node)
</span><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand stringOrSymbol(this, node->child1());
</span><span class="lines">@@ -11119,10 +11149,24 @@
</span><span class="cx">     auto typedArrayType = node->typedArrayType();
</span><span class="cx">     RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
</span><span class="cx">     RELEASE_ASSERT(structure.get());
</span><del>-    
</del><ins>+
+#if USE(LARGE_TYPED_ARRAYS)
+    // The operations we call on the slow path expect a intptr_t, so int64_t on 64 bit platforms
</ins><span class="cx">     SpeculateInt32Operand size(this, node->child1());
</span><ins>+    GPRTemporary scratch(this);
</ins><span class="cx">     GPRReg sizeGPR = size.gpr();
</span><del>-    
</del><ins>+    GPRReg scratchGPR = scratch.gpr();
+    m_jit.signExtend32ToPtr(sizeGPR, scratchGPR);
+    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, scratchGPR);
+#else
+    SpeculateInt32Operand size(this, node->child1());
+    GPRReg sizeGPR = size.gpr();
+    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR);
+#endif
+}
+
+void SpeculativeJIT::emitNewTypedArrayWithSizeInRegister(Node* node, TypedArrayType typedArrayType, RegisteredStructure structure, GPRReg sizeGPR)
+{
</ins><span class="cx">     GPRTemporary result(this);
</span><span class="cx">     GPRTemporary storage(this);
</span><span class="cx">     GPRTemporary scratch(this);
</span><span class="lines">@@ -11136,8 +11180,15 @@
</span><span class="cx">     
</span><span class="cx">     m_jit.move(TrustedImmPtr(nullptr), storageGPR);
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    slowCases.append(m_jit.branch64(
+        MacroAssembler::Above, sizeGPR, TrustedImm64(JSArrayBufferView::fastSizeLimit)));
+    // We assume through the rest of the fast path that the size is a 32-bit number.
+    static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit));
+#else
</ins><span class="cx">     slowCases.append(m_jit.branch32(
</span><span class="cx">         MacroAssembler::Above, sizeGPR, TrustedImm32(JSArrayBufferView::fastSizeLimit)));
</span><ins>+#endif
</ins><span class="cx">     
</span><span class="cx">     m_jit.move(sizeGPR, scratchGPR);
</span><span class="cx">     m_jit.lshift32(TrustedImm32(logElementSize(typedArrayType)), scratchGPR);
</span><span class="lines">@@ -11193,9 +11244,15 @@
</span><span class="cx">     m_jit.storePtr(
</span><span class="cx">         storageGPR,
</span><span class="cx">         MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector()));
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    m_jit.store64(
+        sizeGPR,
+        MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
+#else
</ins><span class="cx">     m_jit.store32(
</span><span class="cx">         sizeGPR,
</span><span class="cx">         MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength()));
</span><ins>+#endif
</ins><span class="cx">     m_jit.store32(
</span><span class="cx">         TrustedImm32(FastTypedArray),
</span><span class="cx">         MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfMode()));
</span><span class="lines">@@ -14167,6 +14224,11 @@
</span><span class="cx">     case Int32Use:
</span><span class="cx">         compileNewTypedArrayWithSize(node);
</span><span class="cx">         break;
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    case Int52RepUse:
+        compileNewTypedArrayWithInt52Size(node);
+        break;
+#endif
</ins><span class="cx">     case UntypedUse: {
</span><span class="cx">         JSValueOperand argument(this, node->child1());
</span><span class="cx">         JSValueRegs argumentRegs = argument.jsValueRegs();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1300,9 +1300,13 @@
</span><span class="cx">     void compileNumberToStringWithValidRadixConstant(Node*, int32_t radix);
</span><span class="cx">     void compileNewStringObject(Node*);
</span><span class="cx">     void compileNewSymbol(Node*);
</span><del>-    
</del><ins>+
+    void emitNewTypedArrayWithSizeInRegister(Node*, TypedArrayType, RegisteredStructure, GPRReg sizeGPR);
</ins><span class="cx">     void compileNewTypedArrayWithSize(Node*);
</span><del>-    
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    void compileNewTypedArrayWithInt52Size(Node*);
+#endif
+
</ins><span class="cx">     void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
</span><span class="cx">     void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
</span><span class="cx"> #if USE(BIGINT32)
</span><span class="lines">@@ -1373,6 +1377,9 @@
</span><span class="cx">     void compileGetGlobalThis(Node*);
</span><span class="cx"> 
</span><span class="cx">     void compileGetArrayLength(Node*);
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    void compileGetTypedArrayLengthAsInt52(Node*);
+#endif
</ins><span class="cx"> 
</span><span class="cx">     void compileCheckTypeInfoFlags(Node*);
</span><span class="cx">     void compileCheckIdent(Node*);
</span><span class="lines">@@ -1431,10 +1438,13 @@
</span><span class="cx">     void compileArithMinMax(Node*);
</span><span class="cx">     void compileConstantStoragePointer(Node*);
</span><span class="cx">     void compileGetIndexedPropertyStorage(Node*);
</span><del>-    JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR);
</del><ins>+    JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR);
</ins><span class="cx">     JITCompiler::Jump jumpForTypedArrayIsDetachedIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds);
</span><del>-    void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR);
</del><ins>+    void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR);
</ins><span class="cx">     void compileGetTypedArrayByteOffset(Node*);
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    void compileGetTypedArrayByteOffsetAsInt52(Node*);
+#endif
</ins><span class="cx">     void compileGetByValOnIntTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</span><span class="cx">     void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType);
</span><span class="cx">     void compileGetByValOnFloatTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix);
</span><span class="lines">@@ -2427,7 +2437,7 @@
</span><span class="cx">     GPRReg m_gprOrInvalid;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero).
</del><ins>+// Gives you a canonical Int52 (i.e. it's left-shifted by 12, low bits zero).
</ins><span class="cx"> class SpeculateInt52Operand {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="lines">@@ -2475,7 +2485,7 @@
</span><span class="cx">     GPRReg m_gprOrInvalid;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended).
</del><ins>+// Gives you a strict Int52 (i.e. the payload is in the low 52 bits, high 12 bits are sign-extended).
</ins><span class="cx"> class SpeculateStrictInt52Operand {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -2136,6 +2136,7 @@
</span><span class="cx">         compileGetByValOnScopedArguments(node, prefix);
</span><span class="cx">         break;
</span><span class="cx">     default: {
</span><ins>+        ASSERT(node->arrayMode().isSomeTypedArrayView());
</ins><span class="cx">         TypedArrayType type = node->arrayMode().typedArrayType();
</span><span class="cx">         if (isInt(type))
</span><span class="cx">             compileGetByValOnIntTypedArray(node, type, prefix);
</span><span class="lines">@@ -3540,6 +3541,11 @@
</span><span class="cx">         compileGetArrayLength(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayLengthAsInt52:
+        // We do not support typed arrays larger than 2GB on 32-bit platforms.
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+
</ins><span class="cx">     case DeleteById: {
</span><span class="cx">         compileDeleteById(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -3622,6 +3628,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayByteOffsetAsInt52: {
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+
</ins><span class="cx">     case GetPrototypeOf: {
</span><span class="cx">         compileGetPrototypeOf(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -4400,6 +4411,7 @@
</span><span class="cx">     case Int52Constant:
</span><span class="cx">     case AssertInBounds:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case ArithIMul:
</span><span class="cx">     case MultiGetByOffset:
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -2694,6 +2694,86 @@
</span><span class="cx">     } }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+void SpeculativeJIT::compileNewTypedArrayWithInt52Size(Node* node)
+{
+    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
+    auto typedArrayType = node->typedArrayType();
+    RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
+    RELEASE_ASSERT(structure.get());
+
+    SpeculateStrictInt52Operand size(this, node->child1());
+    GPRReg sizeGPR = size.gpr();
+
+    emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR);
+}
+
+void SpeculativeJIT::compileGetTypedArrayLengthAsInt52(Node* node)
+{
+    RELEASE_ASSERT(node->arrayMode().isSomeTypedArrayView());
+    SpeculateCellOperand base(this, node->child1());
+    GPRTemporary result(this, Reuse, base);
+    GPRReg baseGPR = base.gpr();
+    GPRReg resultGPR = result.gpr();
+    m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR);
+    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");
+    strictInt52Result(resultGPR, node);
+}
+
+void SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52(Node* node)
+{
+    SpeculateCellOperand base(this, node->child1());
+    GPRTemporary vector(this);
+    GPRTemporary data(this);
+
+    GPRReg baseGPR = base.gpr();
+    GPRReg vectorGPR = vector.gpr();
+    GPRReg dataGPR = data.gpr();
+
+    GPRReg arrayBufferGPR = dataGPR;
+
+    JITCompiler::Jump emptyByteOffset = m_jit.branch32(
+        MacroAssembler::NotEqual,
+        MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()),
+        TrustedImm32(WastefulTypedArray));
+
+    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
+
+    JITCompiler::Jump nullVector = m_jit.branchPtr(JITCompiler::Equal, vectorGPR, TrustedImmPtr(JSArrayBufferView::nullVectorPtr()));
+
+    m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
+    m_jit.cageWithoutUntagging(Gigacage::JSValue, dataGPR);
+
+    cageTypedArrayStorage(baseGPR, vectorGPR);
+
+    m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR);
+    // FIXME: This needs caging.
+    // https://bugs.webkit.org/show_bug.cgi?id=175515
+    m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR);
+#if CPU(ARM64E)
+    m_jit.removeArrayPtrTag(dataGPR);
+#endif
+
+    m_jit.subPtr(dataGPR, vectorGPR);
+
+    JITCompiler::Jump done = m_jit.jump();
+
+#if CPU(ARM64E)
+    nullVector.link(&m_jit);
+#endif
+    emptyByteOffset.link(&m_jit);
+    m_jit.move(TrustedImmPtr(nullptr), vectorGPR);
+
+    done.link(&m_jit);
+#if !CPU(ARM64E)
+    ASSERT(!JSArrayBufferView::nullVectorPtr());
+    nullVector.link(&m_jit);
+#endif
+
+    strictInt52Result(vectorGPR, node);
+}
+#endif // USE(LARGE_TYPED_ARRAYS)
+
</ins><span class="cx"> void SpeculativeJIT::compile(Node* node)
</span><span class="cx"> {
</span><span class="cx">     NodeType op = node->op();
</span><span class="lines">@@ -3644,11 +3724,12 @@
</span><span class="cx">         
</span><span class="cx">         SpeculateCellOperand base(this, baseEdge);
</span><span class="cx">         SpeculateStrictInt32Operand index(this, indexEdge);
</span><ins>+        GPRTemporary scratch (this);
</ins><span class="cx"> 
</span><span class="cx">         baseGPR = base.gpr();
</span><span class="cx">         indexGPR = index.gpr();
</span><span class="cx">         
</span><del>-        emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
</del><ins>+        emitTypedArrayBoundsCheck(node, baseGPR, indexGPR, scratch.gpr());
</ins><span class="cx">         
</span><span class="cx">         GPRTemporary args[2];
</span><span class="cx">         
</span><span class="lines">@@ -4381,6 +4462,14 @@
</span><span class="cx">         compileGetArrayLength(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayLengthAsInt52:
+#if USE(ADDRESS64)
+        compileGetTypedArrayLengthAsInt52(node);
+#else
+        RELEASE_ASSERT_NOT_REACHED();
+#endif
+        break;
+
</ins><span class="cx">     case DeleteById: {
</span><span class="cx">         compileDeleteById(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -4499,6 +4588,15 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetTypedArrayByteOffsetAsInt52: {
+#if USE(LARGE_TYPED_ARRAYS)
+        compileGetTypedArrayByteOffsetAsInt52(node);
+#else
+        RELEASE_ASSERT_NOT_REACHED();
+#endif
+        break;
+    }
+
</ins><span class="cx">     case GetPrototypeOf: {
</span><span class="cx">         compileGetPrototypeOf(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -5589,7 +5687,14 @@
</span><span class="cx">         m_jit.zeroExtend32ToWord(indexGPR, t2);
</span><span class="cx">         if (data.byteSize > 1)
</span><span class="cx">             m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        speculationCheck(OutOfBounds, JSValueRegs(), node,
+            m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0)));
+        m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
+#else
+        // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after
</ins><span class="cx">         m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
</span><ins>+#endif
</ins><span class="cx">         speculationCheck(OutOfBounds, JSValueRegs(), node,
</span><span class="cx">             m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
</span><span class="cx"> 
</span><span class="lines">@@ -5790,7 +5895,14 @@
</span><span class="cx">         m_jit.zeroExtend32ToWord(indexGPR, t2);
</span><span class="cx">         if (data.byteSize > 1)
</span><span class="cx">             m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        speculationCheck(OutOfBounds, JSValueRegs(), node,
+            m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0)));
+        m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
+#else
+        // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after
</ins><span class="cx">         m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
</span><ins>+#endif
</ins><span class="cx">         speculationCheck(OutOfBounds, JSValueRegs(), node,
</span><span class="cx">             m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
</span><span class="cx"> 
</span><span class="lines">@@ -6042,6 +6154,7 @@
</span><span class="cx">     case ExtractOSREntryLocal:
</span><span class="cx">     case AssertInBounds:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case ArithIMul:
</span><span class="cx">     case MultiGetByOffset:
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -279,10 +279,12 @@
</span><span class="cx">                 case PutByVal:
</span><span class="cx">                 case PutByValAlias:
</span><span class="cx">                 case GetArrayLength:
</span><ins>+                case GetTypedArrayLengthAsInt52:
</ins><span class="cx">                 case CheckArray:
</span><span class="cx">                 case CheckDetached:
</span><span class="cx">                 case GetIndexedPropertyStorage:
</span><span class="cx">                 case GetTypedArrayByteOffset:
</span><ins>+                case GetTypedArrayByteOffsetAsInt52:
</ins><span class="cx">                 case Phantom:
</span><span class="cx">                 case MovHint:
</span><span class="cx">                 case MultiGetByOffset:
</span><span class="lines">@@ -359,6 +361,7 @@
</span><span class="cx">                 case PutByVal:
</span><span class="cx">                 case PutByValAlias:
</span><span class="cx">                 case GetArrayLength:
</span><ins>+                case GetTypedArrayLengthAsInt52:
</ins><span class="cx">                 case GetIndexedPropertyStorage:
</span><span class="cx">                 case Phantom:
</span><span class="cx">                 case MovHint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -640,6 +640,7 @@
</span><span class="cx">                 case Upsilon:
</span><span class="cx">                 case AssertInBounds:
</span><span class="cx">                 case CheckInBounds:
</span><ins>+                case CheckInBoundsInt52:
</ins><span class="cx">                 case PhantomNewObject:
</span><span class="cx">                 case PhantomNewFunction:
</span><span class="cx">                 case PhantomNewGeneratorFunction:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -170,6 +170,7 @@
</span><span class="cx">     case ReallocatePropertyStorage:
</span><span class="cx">     case NukeStructureAndSetButterfly:
</span><span class="cx">     case GetTypedArrayByteOffset:
</span><ins>+    case GetTypedArrayByteOffsetAsInt52:
</ins><span class="cx">     case GetPrototypeOf:
</span><span class="cx">     case NotifyWrite:
</span><span class="cx">     case StoreBarrier:
</span><span class="lines">@@ -199,6 +200,7 @@
</span><span class="cx">     case LogicalNot:
</span><span class="cx">     case AssertInBounds:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case CheckInBoundsInt52:
</ins><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case Check:
</span><span class="cx">     case CheckVarargs:
</span><span class="lines">@@ -391,6 +393,7 @@
</span><span class="cx">     case InitializeEntrypointArguments:
</span><span class="cx">     case CPUIntrinsic:
</span><span class="cx">     case GetArrayLength:
</span><ins>+    case GetTypedArrayLengthAsInt52:
</ins><span class="cx">     case GetVectorLength:
</span><span class="cx">     case GetByVal:
</span><span class="cx">     case GetByValWithThis:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -605,6 +605,8 @@
</span><span class="cx">                 continue;
</span><span class="cx">             if (node->op() == CheckInBounds)
</span><span class="cx">                 continue;
</span><ins>+            if (node->op() == CheckInBoundsInt52)
+                continue;
</ins><span class="cx"> 
</span><span class="cx">             AbstractValue value = m_interpreter.forNode(node);
</span><span class="cx">             {
</span><span class="lines">@@ -1025,6 +1027,9 @@
</span><span class="cx">         case GetArrayLength:
</span><span class="cx">             compileGetArrayLength();
</span><span class="cx">             break;
</span><ins>+        case GetTypedArrayLengthAsInt52:
+            compileGetTypedArrayLengthAsInt52();
+            break;
</ins><span class="cx">         case GetVectorLength:
</span><span class="cx">             compileGetVectorLength();
</span><span class="cx">             break;
</span><span class="lines">@@ -1034,6 +1039,9 @@
</span><span class="cx">         case CheckInBounds:
</span><span class="cx">             compileCheckInBounds();
</span><span class="cx">             break;
</span><ins>+        case CheckInBoundsInt52:
+            compileCheckInBoundsInt52();
+            break;
</ins><span class="cx">         case GetByVal:
</span><span class="cx">             compileGetByVal();
</span><span class="cx">             break;
</span><span class="lines">@@ -1175,6 +1183,9 @@
</span><span class="cx">         case GetTypedArrayByteOffset:
</span><span class="cx">             compileGetTypedArrayByteOffset();
</span><span class="cx">             break;
</span><ins>+        case GetTypedArrayByteOffsetAsInt52:
+            compileGetTypedArrayByteOffsetAsInt52();
+            break;
</ins><span class="cx">         case GetPrototypeOf:
</span><span class="cx">             compileGetPrototypeOf();
</span><span class="cx">             break;
</span><span class="lines">@@ -4828,9 +4839,9 @@
</span><span class="cx">             m_out.isNull(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileGetTypedArrayByteOffset()
</del><ins>+    LValue emitGetTypedArrayByteOffsetExceptSettingResult()
</ins><span class="cx">     {
</span><del>-        LValue basePtr = lowCell(m_node->child1());    
</del><ins>+        LValue basePtr = lowCell(m_node->child1());
</ins><span class="cx"> 
</span><span class="cx">         LBasicBlock wastefulCase = m_out.newBlock();
</span><span class="cx">         LBasicBlock notNull = m_out.newBlock();
</span><span class="lines">@@ -4846,7 +4857,7 @@
</span><span class="cx">         LBasicBlock lastNext = m_out.appendTo(wastefulCase, notNull);
</span><span class="cx"> 
</span><span class="cx">         LValue vector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector);
</span><del>-        m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())), 
</del><ins>+        m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())),
</ins><span class="cx">             unsure(continuation), unsure(notNull));
</span><span class="cx"> 
</span><span class="cx">         m_out.appendTo(notNull, continuation);
</span><span class="lines">@@ -4866,9 +4877,29 @@
</span><span class="cx">         m_out.jump(continuation);
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx"> 
</span><del>-        setInt32(m_out.castToInt32(m_out.phi(pointerType(), nullVectorOut, wastefulOut)));
</del><ins>+        return m_out.phi(pointerType(), nullVectorOut, wastefulOut);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void compileGetTypedArrayByteOffset()
+    {
+        LValue result = emitGetTypedArrayByteOffsetExceptSettingResult();
+#if USE(LARGE_TYPED_ARRAYS)
+        // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here.
+        speculate(Overflow, noValue(), nullptr, m_out.above(result, m_out.constInt64(std::numeric_limits<int32_t>::max())));
+#endif
+        setInt32(m_out.castToInt32(result));
+    }
+
+IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
+    void compileGetTypedArrayByteOffsetAsInt52()
+    {
+        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
+        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
+        LValue result = emitGetTypedArrayByteOffsetExceptSettingResult();
+        setStrictInt52(result);
+    }
+IGNORE_CLANG_WARNINGS_END
+
</ins><span class="cx">     void compileGetPrototypeOf()
</span><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><span class="lines">@@ -5054,8 +5085,13 @@
</span><span class="cx">             
</span><span class="cx">         default:
</span><span class="cx">             if (m_node->arrayMode().isSomeTypedArrayView()) {
</span><del>-                setInt32(
-                    m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+                LValue length = m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length);
+                speculate(Overflow, noValue(), nullptr, m_out.above(length, m_out.constInt64(std::numeric_limits<int32_t>::max())));
+                setInt32(m_out.castToInt32(length));
+#else
+                setInt32(m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
+#endif
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="lines">@@ -5064,6 +5100,16 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
+    void compileGetTypedArrayLengthAsInt52()
+    {
+        RELEASE_ASSERT(m_node->arrayMode().isSomeTypedArrayView());
+        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
+        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
+        setStrictInt52(m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
+    }
+IGNORE_CLANG_WARNINGS_END
+
</ins><span class="cx">     void compileGetVectorLength()
</span><span class="cx">     {
</span><span class="cx">         switch (m_node->arrayMode().type()) {
</span><span class="lines">@@ -5108,7 +5154,22 @@
</span><span class="cx">         // depend on our value. Users of this node just need to maintain that
</span><span class="cx">         // we dominate them.
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn")
+    void compileCheckInBoundsInt52()
+    {
+        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
+        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
+        // Sign-extended to also catch negative indices
+        LValue index = m_out.signExt32To64(lowInt32(m_node->child1()));
+        LValue length = lowStrictInt52(m_node->child2());
+        speculate(OutOfBounds, noValue(), nullptr, m_out.aboveOrEqual(index, length));
+        // Even though we claim to have JSValue result, no user of us should
+        // depend on our value. Users of this node just need to maintain that
+        // we dominate them.
+    }
+IGNORE_CLANG_WARNINGS_END
+
</ins><span class="cx">     LValue compileGetByValImpl()
</span><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic);
</span><span class="lines">@@ -6008,11 +6069,18 @@
</span><span class="cx">                     LBasicBlock isInBounds = m_out.newBlock();
</span><span class="cx">                     LBasicBlock isOutOfBounds = m_out.newBlock();
</span><span class="cx">                     LBasicBlock continuation = m_out.newBlock();
</span><del>-                    
-                    m_out.branch(
-                        m_out.aboveOrEqual(index, lowInt32(child5)),
-                        unsure(isOutOfBounds), unsure(isInBounds));
-                    
</del><ins>+
+                    LValue isOutOfBoundsCondition;
+                    if (child5.useKind() == Int52RepUse) {
+                        // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent.
+                        RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t));
+                        isOutOfBoundsCondition = m_out.aboveOrEqual(m_out.signExt32To64(index), lowStrictInt52(child5));
+                    } else {
+                        ASSERT(child5.useKind() == Int32Use);
+                        isOutOfBoundsCondition = m_out.aboveOrEqual(index, lowInt32(child5));
+                    }
+                    m_out.branch(isOutOfBoundsCondition, unsure(isOutOfBounds), unsure(isInBounds));
+
</ins><span class="cx">                     LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds);
</span><span class="cx">                     m_out.store(valueToStore, pointer, storeType(type));
</span><span class="cx">                     m_out.jump(continuation);
</span><span class="lines">@@ -8169,95 +8237,18 @@
</span><span class="cx">         case Int32Use: {
</span><span class="cx">             RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
</span><span class="cx"> 
</span><del>-            LValue size = lowInt32(m_node->child1());
</del><ins>+            LValue size = m_out.signExt32To64(lowInt32(m_node->child1()));
</ins><span class="cx"> 
</span><del>-            LBasicBlock smallEnoughCase = m_out.newBlock();
-            LBasicBlock slowCase = m_out.newBlock();
-            LBasicBlock continuation = m_out.newBlock();
-            
-            ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero);
</del><ins>+            emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size);
+            return;
+        }
</ins><span class="cx"> 
</span><del>-            m_out.branch(
-                m_out.above(size, m_out.constInt32(JSArrayBufferView::fastSizeLimit)),
-                rarely(slowCase), usually(smallEnoughCase));
</del><ins>+        case Int52RepUse: {
+            RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType));
</ins><span class="cx"> 
</span><del>-            LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase);
</del><ins>+            LValue size = lowStrictInt52(m_node->child1());
</ins><span class="cx"> 
</span><del>-            LValue byteSize =
-                m_out.shl(m_out.zeroExtPtr(size), m_out.constInt32(logElementSize(typedArrayType)));
-            if (elementSize(typedArrayType) < 8) {
-                byteSize = m_out.bitAnd(
-                    m_out.add(byteSize, m_out.constIntPtr(7)),
-                    m_out.constIntPtr(~static_cast<intptr_t>(7)));
-            }
-        
-            LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase);
-            LValue storage = allocateHeapCell(allocator, slowCase);
-            
-            splatWords(
-                storage,
-                m_out.int32Zero,
-                m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))),
-                m_out.int64Zero,
-                m_heaps.typedArrayProperties);
-
-#if CPU(ARM64E)
-            {
-                LValue sizePtr = m_out.zeroExtPtr(size);
-                PatchpointValue* authenticate = m_out.patchpoint(pointerType());
-                authenticate->appendSomeRegister(storage);
-                authenticate->append(sizePtr, B3::ValueRep(B3::ValueRep::SomeLateRegister));
-                authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
-                    jit.move(params[1].gpr(), params[0].gpr());
-                    jit.tagArrayPtr(params[2].gpr(), params[0].gpr());
-                });
-                storage = authenticate;
-            }
-#endif
-
-            ValueFromBlock haveStorage = m_out.anchor(storage);
-
-            LValue fastResultValue = nullptr;
-            switch (typedArrayType) {
-#define TYPED_ARRAY_TYPE_CASE(name) \
-            case Type ## name: \
-                fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \
-                break;
-            FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE)
-#undef TYPED_ARRAY_TYPE_CASE
-            case TypeDataView:
-                fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase);
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
-
-            m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
-            m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
-            m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
-            
-            mutatorFence();
-            ValueFromBlock fastResult = m_out.anchor(fastResultValue);
-            m_out.jump(continuation);
-
-            m_out.appendTo(slowCase, continuation);
-            LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage);
-
-            VM& vm = this->vm();
-            LValue slowResultValue = lazySlowPath(
-                [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
-                    return createLazyCallGenerator(vm,
-                        operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject,
-                        CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
-                        locations[2].directGPR());
-                },
-                size, storageValue);
-            ValueFromBlock slowResult = m_out.anchor(slowResultValue);
-            m_out.jump(continuation);
-
-            m_out.appendTo(continuation, lastNext);
-            setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
</del><ins>+            emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -8277,7 +8268,104 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void emitNewTypedArrayWithSize(TypedArrayType typedArrayType, JSGlobalObject* globalObject, RegisteredStructure structure, LValue size64Bits)
+    {
+        LBasicBlock smallEnoughCase = m_out.newBlock();
+        LBasicBlock slowCase = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero);
+
+        m_out.branch(
+            m_out.above(size64Bits, m_out.constInt64(JSArrayBufferView::fastSizeLimit)),
+            rarely(slowCase), usually(smallEnoughCase));
+
+        LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase);
+        // We assume through the rest of the fast path that the size is a 32-bit number.
+        static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit));
+
+        LValue byteSize =
+            m_out.shl(size64Bits, m_out.constInt32(logElementSize(typedArrayType)));
+        if (elementSize(typedArrayType) < 8) {
+            byteSize = m_out.bitAnd(
+                m_out.add(byteSize, m_out.constIntPtr(7)),
+                m_out.constIntPtr(~static_cast<intptr_t>(7)));
+        }
+
+        LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase);
+        LValue storage = allocateHeapCell(allocator, slowCase);
+
+        splatWords(
+            storage,
+            m_out.int32Zero,
+            m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))),
+            m_out.int64Zero,
+            m_heaps.typedArrayProperties);
+
+#if CPU(ARM64E)
+        {
+            PatchpointValue* authenticate = m_out.patchpoint(pointerType());
+            authenticate->appendSomeRegister(storage);
+            authenticate->append(size64Bits, B3::ValueRep(B3::ValueRep::SomeLateRegister));
+            authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+                jit.move(params[1].gpr(), params[0].gpr());
+                jit.tagArrayPtr(params[2].gpr(), params[0].gpr());
+            });
+            storage = authenticate;
+        }
+#endif
+
+        ValueFromBlock haveStorage = m_out.anchor(storage);
+
+        LValue fastResultValue = nullptr;
+        switch (typedArrayType) {
+#define TYPED_ARRAY_TYPE_CASE(name) \
+        case Type ## name: \
+            fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \
+            break;
+        FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE)
+#undef TYPED_ARRAY_TYPE_CASE
+        case TypeDataView:
+            fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+
+        m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
+#if USE(LARGE_TYPED_ARRAYS)
+        m_out.store64(size64Bits, fastResultValue, m_heaps.JSArrayBufferView_length);
+#else
+        m_out.store32(m_out.castToInt32(size64Bits), fastResultValue, m_heaps.JSArrayBufferView_length);
+#endif
+        m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
+
+        mutatorFence();
+        ValueFromBlock fastResult = m_out.anchor(fastResultValue);
+        m_out.jump(continuation);
+
+        m_out.appendTo(slowCase, continuation);
+        LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage);
+
+        VM& vm = this->vm();
+        LValue slowResultValue = lazySlowPath(
+            [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
+                return createLazyCallGenerator(vm,
+                    operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject,
+                    CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
+                    locations[2].directGPR());
+            },
+            size64Bits, storageValue);
+        ValueFromBlock slowResult = m_out.anchor(slowResultValue);
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
+        return;
+    }
+
</ins><span class="cx">     void compileAllocatePropertyStorage()
</span><span class="cx">     {
</span><span class="cx">         LValue object = lowCell(m_node->child1());
</span><span class="lines">@@ -14656,6 +14744,8 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // base and value are 64-bits, begin and end are 32-bits
+    // stores value at every 64-bits word between base+begin*8 and base+end*8
</ins><span class="cx">     void splatWords(LValue base, LValue begin, LValue end, LValue value, const AbstractHeap& heap)
</span><span class="cx">     {
</span><span class="cx">         const uint64_t unrollingLimit = 10;
</span><span class="lines">@@ -15591,7 +15681,13 @@
</span><span class="cx"> 
</span><span class="cx">         DataViewData data = m_node->dataViewData();
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0)));
+        LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length);
+#else
+        // No need for an explicit comparison of index to 0, the check against length catches that case
</ins><span class="cx">         LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length));
</span><ins>+#endif
</ins><span class="cx">         LValue indexToCheck = m_out.zeroExtPtr(index);
</span><span class="cx">         if (data.byteSize > 1)
</span><span class="cx">             indexToCheck = m_out.add(indexToCheck, m_out.constInt64(data.byteSize - 1));
</span><span class="lines">@@ -15734,7 +15830,13 @@
</span><span class="cx"> 
</span><span class="cx">         DataViewData data = m_node->dataViewData();
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0)));
+        LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length);
+#else
+        // No need for an explicit comparison of index to 0, the check against length catches that case
</ins><span class="cx">         LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length));
</span><ins>+#endif
</ins><span class="cx">         LValue indexToCheck = m_out.zeroExtPtr(index);
</span><span class="cx">         if (data.byteSize > 1)
</span><span class="cx">             indexToCheck = m_out.add(indexToCheck, m_out.constInt64(data.byteSize - 1));
</span><span class="lines">@@ -17236,7 +17338,11 @@
</span><span class="cx">         auto doUntagArrayPtr = [&](LValue taggedPtr) {
</span><span class="cx"> #if CPU(ARM64E)
</span><span class="cx">             if (kind == Gigacage::Primitive) {
</span><ins>+#if USE(ADDRESS64)
+                LValue size = m_out.load64(base, m_heaps.JSArrayBufferView_length);
+#else
</ins><span class="cx">                 LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length);
</span><ins>+#endif
</ins><span class="cx">                 return untagArrayPtr(taggedPtr, size);
</span><span class="cx">             }
</span><span class="cx">             return ptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -329,6 +329,7 @@
</span><span class="cx">     LValue nonNegative32(LValue loadInstruction) { return loadInstruction; }
</span><span class="cx">     LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); }
</span><span class="cx">     LValue load32NonNegative(LValue base, const AbstractHeap& field) { return load32(base, field); }
</span><ins>+    LValue load64NonNegative(LValue base, const AbstractHeap& field) { return load64(base, field); }
</ins><span class="cx"> 
</span><span class="cx">     LValue equal(LValue, LValue);
</span><span class="cx">     LValue notEqual(LValue, LValue);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitIntrinsicEmittercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -86,8 +86,13 @@
</span><span class="cx"> 
</span><span class="cx">     switch (intrinsic()) {
</span><span class="cx">     case TypedArrayLengthIntrinsic: {
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
+        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
+#else
</ins><span class="cx">         jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
</span><span class="cx">         jit.boxInt32(valueGPR, valueRegs);
</span><ins>+#endif
</ins><span class="cx">         state.succeed();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -94,15 +99,19 @@
</span><span class="cx"> 
</span><span class="cx">     case TypedArrayByteLengthIntrinsic: {
</span><span class="cx">         TypedArrayType type = structure()->classInfo()->typedArrayStorageType;
</span><del>-
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+        jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
+        if (elementSize(type) > 1)
+            jit.lshift64(TrustedImm32(logElementSize(type)), valueGPR);
+        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
+#else
</ins><span class="cx">         jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR);
</span><del>-
</del><span class="cx">         if (elementSize(type) > 1) {
</span><del>-            // We can use a bitshift here since we TypedArrays cannot have byteLength that overflows an int32.
-            jit.lshift32(valueGPR, Imm32(logElementSize(type)), valueGPR);
</del><ins>+            // We can use a bitshift here since on ADDRESS32 platforms TypedArrays cannot have byteLength that overflows an int32.
+            jit.lshift32(TrustedImm32(logElementSize(type)), valueGPR);
</ins><span class="cx">         }
</span><del>-
</del><span class="cx">         jit.boxInt32(valueGPR, valueRegs);
</span><ins>+#endif
</ins><span class="cx">         state.succeed();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -133,8 +142,12 @@
</span><span class="cx">         jit.move(TrustedImmPtr(nullptr), valueGPR);
</span><span class="cx">         
</span><span class="cx">         done.link(&jit);
</span><del>-        
</del><ins>+
+#if USE(LARGE_TYPED_ARRAYS)
+        jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR);
+#else
</ins><span class="cx">         jit.boxInt32(valueGPR, valueRegs);
</span><ins>+#endif
</ins><span class="cx">         state.succeed();
</span><span class="cx">         return;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -937,10 +937,8 @@
</span><span class="cx">         uint32_t i = *index;
</span><span class="cx">         if (baseValue.isObject()) {
</span><span class="cx">             JSObject* object = asObject(baseValue);
</span><del>-            if (object->canSetIndexQuickly(i, value)) {
-                object->setIndexQuickly(vm, i, value);
</del><ins>+            if (object->trySetIndexQuickly(vm, i, value, arrayProfile))
</ins><span class="cx">                 return;
</span><del>-            }
</del><span class="cx"> 
</span><span class="cx">             if (arrayProfile)
</span><span class="cx">                 arrayProfile->setOutOfBounds();
</span><span class="lines">@@ -2342,21 +2340,22 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (std::optional<int32_t> index = subscript.tryGetAsInt32()) {
-        int32_t i = *index;
</del><ins>+    if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
+        uint32_t i = *index;
</ins><span class="cx">         if (isJSString(baseValue)) {
</span><del>-            if (i >= 0 && asString(baseValue)->canGetIndex(i))
</del><ins>+            if (asString(baseValue)->canGetIndex(i))
</ins><span class="cx">                 RELEASE_AND_RETURN(scope, asString(baseValue)->getIndex(globalObject, i));
</span><span class="cx">             if (arrayProfile)
</span><span class="cx">                 arrayProfile->setOutOfBounds();
</span><span class="cx">         } else if (baseValue.isObject()) {
</span><span class="cx">             JSObject* object = asObject(baseValue);
</span><del>-            if (object->canGetIndexQuickly(static_cast<uint32_t>(i)))
-                return object->getIndexQuickly(i);
</del><ins>+            if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile))
+                return result;
</ins><span class="cx"> 
</span><span class="cx">             bool skipMarkingOutOfBounds = false;
</span><span class="cx"> 
</span><del>-            if (object->indexingType() == ArrayWithContiguous && i >= 0 && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) {
</del><ins>+            if (object->indexingType() == ArrayWithContiguous
+                && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) {
</ins><span class="cx">                 // FIXME: expand this to ArrayStorage, Int32, and maybe Double:
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=182940
</span><span class="cx">                 auto* globalObject = object->globalObject(vm);
</span><span class="lines">@@ -2372,8 +2371,7 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (i >= 0)
-            RELEASE_AND_RETURN(scope, baseValue.get(globalObject, static_cast<uint32_t>(i)));
</del><ins>+        RELEASE_AND_RETURN(scope, baseValue.get(globalObject, i));
</ins><span class="cx">     } else if (subscript.isNumber() && baseValue.isCell() && arrayProfile)
</span><span class="cx">         arrayProfile->setOutOfBounds();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntOfflineAsmConfigh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -149,6 +149,12 @@
</span><span class="cx"> #define OFFLINE_ASM_BIGINT32 0
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+#define OFFLINE_ASM_LARGE_TYPED_ARRAYS 1
+#else
+#define OFFLINE_ASM_LARGE_TYPED_ARRAYS 0
+#endif
+
</ins><span class="cx"> #if CPU(ADDRESS64)
</span><span class="cx"> #define OFFLINE_ASM_ADDRESS64 1
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1047,8 +1047,8 @@
</span><span class="cx">             arrayProfile->setOutOfBounds();
</span><span class="cx">         } else if (baseValue.isObject()) {
</span><span class="cx">             JSObject* object = asObject(baseValue);
</span><del>-            if (object->canGetIndexQuickly(i))
-                return object->getIndexQuickly(i);
</del><ins>+            if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile))
+                return result;
</ins><span class="cx"> 
</span><span class="cx">             bool skipMarkingOutOfBounds = false;
</span><span class="cx"> 
</span><span class="lines">@@ -1170,14 +1170,13 @@
</span><span class="cx">     JSValue subscript = getOperand(callFrame, bytecode.m_property);
</span><span class="cx">     JSValue value = getOperand(callFrame, bytecode.m_value);
</span><span class="cx">     bool isStrictMode = bytecode.m_ecmaMode.isStrict();
</span><ins>+    auto& metadata = bytecode.metadata(codeBlock);
</ins><span class="cx">     
</span><span class="cx">     if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
</span><span class="cx">         uint32_t i = *index;
</span><span class="cx">         if (baseValue.isObject()) {
</span><span class="cx">             JSObject* object = asObject(baseValue);
</span><del>-            if (object->canSetIndexQuickly(i, value))
-                object->setIndexQuickly(vm, i, value);
-            else
</del><ins>+            if (!object->trySetIndexQuickly(vm, i, value, &metadata.m_arrayProfile))
</ins><span class="cx">                 object->methodTable(vm)->putByIndex(object, globalObject, i, value, isStrictMode);
</span><span class="cx">             LLINT_END();
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -217,6 +217,10 @@
</span><span class="cx">     const StructureEntropyBitsShift = constexpr StructureIDTable::s_entropyBitsShiftForStructurePointer
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+if LARGE_TYPED_ARRAYS
+    const SmallTypedArrayMaxLength = constexpr ArrayProfile::s_smallTypedArrayMaxLength
+end
+
</ins><span class="cx"> const maxFrameExtentForSlowPathCall = constexpr maxFrameExtentForSlowPathCall
</span><span class="cx"> 
</span><span class="cx"> if X86_64 or X86_64_WIN or ARM64 or ARM64E or RISCV64
</span><span class="lines">@@ -1310,7 +1314,8 @@
</span><span class="cx">     loadb JSCell::m_indexingTypeAndMisc[cell], indexingType
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, slowPath)
</del><ins>+# Note that index is already sign-extended to be a register width.
+macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, slowPath)
</ins><span class="cx">     # First lets check if we even have a typed array. This lets us do some boilerplate up front.
</span><span class="cx">     loadb JSCell::m_type[base], t2
</span><span class="cx">     subi FirstTypedArrayType, t2
</span><span class="lines">@@ -1321,13 +1326,28 @@
</span><span class="cx">     if ARM64E
</span><span class="cx">         const length = t6
</span><span class="cx">         const scratch = t7
</span><del>-        loadi JSArrayBufferView::m_length[base], length
-        biaeq index, length, slowPath
</del><ins>+        if LARGE_TYPED_ARRAYS
+            loadq JSArrayBufferView::m_length[base], length
+            bqaeq index, length, slowPath
+        else
+            loadi JSArrayBufferView::m_length[base], length
+            biaeq index, length, slowPath
+        end
</ins><span class="cx">     else
</span><span class="cx">         # length and scratch are intentionally undefined on this branch because they are not used on other platforms.
</span><del>-        biaeq index, JSArrayBufferView::m_length[base], slowPath
</del><ins>+        if LARGE_TYPED_ARRAYS
+            bqaeq index, JSArrayBufferView::m_length[base], slowPath
+        else
+            biaeq index, JSArrayBufferView::m_length[base], slowPath
+        end
</ins><span class="cx">     end
</span><span class="cx"> 
</span><ins>+    if LARGE_TYPED_ARRAYS
+        bqbeq index, SmallTypedArrayMaxLength, .smallTypedArray
+        setLargeTypedArray()
+.smallTypedArray:
+    end
+
</ins><span class="cx">     loadp JSArrayBufferView::m_vector[base], t3
</span><span class="cx">     cagedPrimitive(t3, length, base, scratch)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1622,6 +1622,10 @@
</span><span class="cx">         dispatch()
</span><span class="cx">     end
</span><span class="cx"> 
</span><ins>+    macro setLargeTypedArray()
+        crash()
+    end
+
</ins><span class="cx">     metadata(t5, t2)
</span><span class="cx">     get(m_base, t2)
</span><span class="cx">     loadConstantOrVariablePayload(size, t2, CellTag, t0, .opGetByValSlow)
</span><span class="lines">@@ -1667,7 +1671,7 @@
</span><span class="cx">     dispatch()
</span><span class="cx"> 
</span><span class="cx"> .opGetByValNotIndexedStorage:
</span><del>-    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)
</del><ins>+    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow)
</ins><span class="cx"> 
</span><span class="cx"> .opGetByValSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_get_by_val)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1713,6 +1713,14 @@
</span><span class="cx">         finishGetByVal(scratch1, scratch2)
</span><span class="cx">     end
</span><span class="cx"> 
</span><ins>+    macro setLargeTypedArray()
+        if LARGE_TYPED_ARRAYS
+            storeb 1, OpGetByVal::Metadata::m_arrayProfile + ArrayProfile::m_mayBeLargeTypedArray[t5]
+        else
+            crash()
+        end
+    end
+
</ins><span class="cx">     metadata(t5, t2)
</span><span class="cx"> 
</span><span class="cx">     get(m_base, t2)
</span><span class="lines">@@ -1723,6 +1731,7 @@
</span><span class="cx"> 
</span><span class="cx">     get(m_property, t3)
</span><span class="cx">     loadConstantOrVariableInt32(size, t3, t1, .opGetByValSlow)
</span><ins>+    # This sign-extension makes the bounds-checking in getByValTypedArray work even on 4GB TypedArray.
</ins><span class="cx">     sxi2q t1, t1
</span><span class="cx"> 
</span><span class="cx">     loadCagedJSValue(JSObject::m_butterfly[t0], t3, numberTag)
</span><span class="lines">@@ -1763,7 +1772,7 @@
</span><span class="cx">     dispatch()
</span><span class="cx"> 
</span><span class="cx"> .opGetByValNotIndexedStorage:
</span><del>-    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)
</del><ins>+    getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow)
</ins><span class="cx"> 
</span><span class="cx"> .opGetByValSlow:
</span><span class="cx">     callSlowPath(_llint_slow_path_get_by_val)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009-2020 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx">     return destructor.get().copyRef();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SharedArrayBufferContents::SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&& destructor)
</del><ins>+SharedArrayBufferContents::SharedArrayBufferContents(void* data, size_t size, ArrayBufferDestructorFunction&& destructor)
</ins><span class="cx">     : m_data(data, size)
</span><span class="cx">     , m_destructor(WTFMove(destructor))
</span><span class="cx">     , m_sizeInBytes(size)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">     other.transferTo(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ArrayBufferContents::ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&& destructor)
</del><ins>+ArrayBufferContents::ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&& destructor)
</ins><span class="cx">     : m_data(data, sizeInBytes)
</span><span class="cx">     , m_sizeInBytes(sizeInBytes)
</span><span class="cx"> {
</span><span class="lines">@@ -109,23 +109,21 @@
</span><span class="cx">     m_sizeInBytes = 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy policy)
</del><ins>+void ArrayBufferContents::tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy policy)
</ins><span class="cx"> {
</span><del>-    // Do not allow 31-bit overflow of the total size.
-    if (numElements) {
-        unsigned totalSize = numElements * elementByteSize;
-        if (totalSize / numElements != elementByteSize || totalSize > MAX_ARRAY_BUFFER_SIZE) {
-            reset();
-            return;
-        }
</del><ins>+    CheckedSize sizeInBytes = numElements;
+    sizeInBytes *= elementByteSize;
+    if (sizeInBytes.hasOverflowed() || sizeInBytes.value() > MAX_ARRAY_BUFFER_SIZE) {
+        reset();
+        return;
</ins><span class="cx">     }
</span><del>-    size_t sizeInBytes = static_cast<size_t>(numElements) * static_cast<size_t>(elementByteSize);
-    size_t allocationSize = sizeInBytes;
</del><ins>+
+    size_t allocationSize = sizeInBytes.value();
</ins><span class="cx">     if (!allocationSize)
</span><span class="cx">         allocationSize = 1; // Make sure malloc actually allocates something, but not too much. We use null to mean that the buffer is detached.
</span><span class="cx"> 
</span><span class="cx">     void* data = Gigacage::tryMalloc(Gigacage::Primitive, allocationSize);
</span><del>-    m_data = DataType(data, sizeInBytes);
</del><ins>+    m_data = DataType(data, sizeInBytes.value());
</ins><span class="cx">     if (!data) {
</span><span class="cx">         reset();
</span><span class="cx">         return;
</span><span class="lines">@@ -134,7 +132,7 @@
</span><span class="cx">     if (policy == ZeroInitialize)
</span><span class="cx">         memset(data, 0, allocationSize);
</span><span class="cx"> 
</span><del>-    m_sizeInBytes = sizeInBytes;
</del><ins>+    m_sizeInBytes = sizeInBytes.value();
</ins><span class="cx">     RELEASE_ASSERT(m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE);
</span><span class="cx">     m_destructor = ArrayBuffer::primitiveGigacageDestructor();
</span><span class="cx"> }
</span><span class="lines">@@ -178,7 +176,7 @@
</span><span class="cx">     RELEASE_ASSERT(other.m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize)
</ins><span class="cx"> {
</span><span class="cx">     auto buffer = tryCreate(numElements, elementByteSize);
</span><span class="cx">     if (!buffer)
</span><span class="lines">@@ -191,7 +189,7 @@
</span><span class="cx">     return ArrayBuffer::create(other.data(), other.byteLength());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::create(const void* source, size_t byteLength)
</ins><span class="cx"> {
</span><span class="cx">     auto buffer = tryCreate(source, byteLength);
</span><span class="cx">     if (!buffer)
</span><span class="lines">@@ -208,7 +206,7 @@
</span><span class="cx"> // Current this is only used from:
</span><span class="cx"> // - JSGenericTypedArrayView<>::slowDownAndWasteMemory. But in that case, the memory should have already come
</span><span class="cx"> //   from the cage.
</span><del>-Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsigned byteLength)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, size_t byteLength)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!Gigacage::isEnabled() || (Gigacage::contains(data) && Gigacage::contains(static_cast<const uint8_t*>(data) + byteLength - 1)));
</span><span class="cx">     return createFromBytes(data, byteLength, ArrayBuffer::primitiveGigacageDestructor());
</span><span class="lines">@@ -220,7 +218,7 @@
</span><span class="cx"> //   longer caged, or we could introduce a new set of typed array types that are uncaged and get accessed
</span><span class="cx"> //   differently.
</span><span class="cx"> // - WebAssembly. Wasm should allocate from the cage.
</span><del>-Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&& destructor)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&& destructor)
</ins><span class="cx"> {
</span><span class="cx">     if (data && !Gigacage::isCaged(Gigacage::Primitive, data))
</span><span class="cx">         Gigacage::disablePrimitiveGigacage();
</span><span class="lines">@@ -229,7 +227,7 @@
</span><span class="cx">     return create(WTFMove(contents));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(unsigned numElements, unsigned elementByteSize)
</del><ins>+RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize)
</ins><span class="cx"> {
</span><span class="cx">     return tryCreate(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize);
</span><span class="cx"> }
</span><span class="lines">@@ -239,7 +237,7 @@
</span><span class="cx">     return tryCreate(other.data(), other.byteLength());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, unsigned byteLength)
</del><ins>+RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, size_t byteLength)
</ins><span class="cx"> {
</span><span class="cx">     ArrayBufferContents contents;
</span><span class="cx">     contents.tryAllocate(byteLength, 1, ArrayBufferContents::DontInitialize);
</span><span class="lines">@@ -248,17 +246,17 @@
</span><span class="cx">     return createInternal(WTFMove(contents), source, byteLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref<ArrayBuffer> ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::createUninitialized(size_t numElements, unsigned elementByteSize)
</ins><span class="cx"> {
</span><span class="cx">     return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized(unsigned numElements, unsigned elementByteSize)
</del><ins>+RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized(size_t numElements, unsigned elementByteSize)
</ins><span class="cx"> {
</span><span class="cx">     return tryCreate(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
</ins><span class="cx"> {
</span><span class="cx">     auto buffer = tryCreate(numElements, elementByteSize, policy);
</span><span class="cx">     if (!buffer)
</span><span class="lines">@@ -266,15 +264,17 @@
</span><span class="cx">     return buffer.releaseNonNull();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, unsigned byteLength)
</del><ins>+Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, size_t byteLength)
</ins><span class="cx"> {
</span><del>-    ASSERT(!byteLength || source);
</del><span class="cx">     auto buffer = adoptRef(*new ArrayBuffer(WTFMove(contents)));
</span><del>-    memcpy(buffer->data(), source, byteLength);
</del><ins>+    if (byteLength) {
+        ASSERT(source);
+        memcpy(buffer->data(), source, byteLength);
+    }
</ins><span class="cx">     return buffer;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
</del><ins>+RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
</ins><span class="cx"> {
</span><span class="cx">     ArrayBufferContents contents;
</span><span class="cx">     contents.tryAllocate(numElements, elementByteSize, policy);
</span><span class="lines">@@ -291,7 +291,7 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned ArrayBuffer::clampValue(double x, unsigned left, unsigned right)
</del><ins>+size_t ArrayBuffer::clampValue(double x, size_t left, size_t right)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(left <= right);
</span><span class="cx">     if (x < left)
</span><span class="lines">@@ -301,9 +301,9 @@
</span><span class="cx">     return x;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned ArrayBuffer::clampIndex(double index) const
</del><ins>+size_t ArrayBuffer::clampIndex(double index) const
</ins><span class="cx"> {
</span><del>-    unsigned currentLength = byteLength();
</del><ins>+    size_t currentLength = byteLength();
</ins><span class="cx">     if (index < 0)
</span><span class="cx">         index = currentLength + index;
</span><span class="cx">     return clampValue(index, 0, currentLength);
</span><span class="lines">@@ -319,9 +319,9 @@
</span><span class="cx">     return sliceWithClampedIndex(clampIndex(begin), byteLength());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(unsigned begin, unsigned end) const
</del><ins>+RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(size_t begin, size_t end) const
</ins><span class="cx"> {
</span><del>-    unsigned size = begin <= end ? end - begin : 0;
</del><ins>+    size_t size = begin <= end ? end - begin : 0;
</ins><span class="cx">     auto result = ArrayBuffer::tryCreate(static_cast<const char*>(data()) + begin, size);
</span><span class="cx">     if (result)
</span><span class="cx">         result->setSharingMode(sharingMode());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayBufferh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009-2018 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include <wtf/CheckedArithmetic.h>
</span><span class="cx"> #include <wtf/PackedRefPtr.h>
</span><span class="cx"> #include <wtf/SharedTask.h>
</span><ins>+#include <wtf/StdIntExtras.h>
</ins><span class="cx"> #include <wtf/StdLibExtras.h>
</span><span class="cx"> #include <wtf/ThreadSafeRefCounted.h>
</span><span class="cx"> #include <wtf/text/WTFString.h>
</span><span class="lines">@@ -39,7 +40,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+#if USE(LARGE_TYPED_ARRAYS)
+static_assert(sizeof(size_t) == sizeof(uint64_t));
+#define MAX_ARRAY_BUFFER_SIZE (1ull << 32)
+#else
+static_assert(sizeof(size_t) == sizeof(uint32_t));
+// Because we are using a size_t to store the size in bytes of array buffers, we cannot support 4GB on 32-bit platforms.
+// So we are sticking with 2GB. It should in theory be possible to support up to (4GB - 1B) if anyone cares.
</ins><span class="cx"> #define MAX_ARRAY_BUFFER_SIZE 0x7fffffffu
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> class VM;
</span><span class="cx"> class ArrayBuffer;
</span><span class="lines">@@ -51,7 +60,7 @@
</span><span class="cx"> 
</span><span class="cx"> class SharedArrayBufferContents : public ThreadSafeRefCounted<SharedArrayBufferContents> {
</span><span class="cx"> public:
</span><del>-    SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&&);
</del><ins>+    SharedArrayBufferContents(void* data, size_t, ArrayBufferDestructorFunction&&);
</ins><span class="cx">     ~SharedArrayBufferContents();
</span><span class="cx">     
</span><span class="cx">     void* data() const { return m_data.getMayBeNull(m_sizeInBytes); }
</span><span class="lines">@@ -60,7 +69,7 @@
</span><span class="cx">     using DataType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
</span><span class="cx">     DataType m_data;
</span><span class="cx">     PackedArrayBufferDestructorFunction m_destructor;
</span><del>-    unsigned m_sizeInBytes;
</del><ins>+    size_t m_sizeInBytes;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class ArrayBufferContents {
</span><span class="lines">@@ -67,7 +76,7 @@
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
</span><span class="cx"> public:
</span><span class="cx">     JS_EXPORT_PRIVATE ArrayBufferContents();
</span><del>-    JS_EXPORT_PRIVATE ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&&);
</del><ins>+    JS_EXPORT_PRIVATE ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&&);
</ins><span class="cx">     
</span><span class="cx">     JS_EXPORT_PRIVATE ArrayBufferContents(ArrayBufferContents&&);
</span><span class="cx">     JS_EXPORT_PRIVATE ArrayBufferContents& operator=(ArrayBufferContents&&);
</span><span class="lines">@@ -79,7 +88,7 @@
</span><span class="cx">     explicit operator bool() { return !!m_data; }
</span><span class="cx">     
</span><span class="cx">     void* data() const { return m_data.getMayBeNull(sizeInBytes()); }
</span><del>-    unsigned sizeInBytes() const { return m_sizeInBytes; }
</del><ins>+    size_t sizeInBytes() const { return m_sizeInBytes; }
</ins><span class="cx">     
</span><span class="cx">     bool isShared() const { return m_shared; }
</span><span class="cx">     
</span><span class="lines">@@ -94,7 +103,7 @@
</span><span class="cx">         DontInitialize
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy);
</del><ins>+    void tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy);
</ins><span class="cx">     
</span><span class="cx">     void makeShared();
</span><span class="cx">     void transferTo(ArrayBufferContents&);
</span><span class="lines">@@ -105,28 +114,28 @@
</span><span class="cx">     DataType m_data;
</span><span class="cx">     PackedArrayBufferDestructorFunction m_destructor;
</span><span class="cx">     PackedRefPtr<SharedArrayBufferContents> m_shared;
</span><del>-    unsigned m_sizeInBytes;
</del><ins>+    size_t m_sizeInBytes;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class ArrayBuffer : public GCIncomingRefCounted<ArrayBuffer> {
</span><span class="cx"> public:
</span><del>-    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
</del><ins>+    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize);
</ins><span class="cx">     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBuffer&);
</span><del>-    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, unsigned byteLength);
</del><ins>+    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, size_t byteLength);
</ins><span class="cx">     JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBufferContents&&);
</span><del>-    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, unsigned byteLength);
-    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&&);
-    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize);
</del><ins>+    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, size_t byteLength);
+    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&&);
+    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize);
</ins><span class="cx">     JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(ArrayBuffer&);
</span><del>-    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, unsigned byteLength);
</del><ins>+    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, size_t byteLength);
</ins><span class="cx"> 
</span><span class="cx">     // Only for use by Uint8ClampedArray::tryCreateUninitialized and SharedBuffer::tryCreateArrayBuffer.
</span><del>-    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
-    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(unsigned numElements, unsigned elementByteSize);
</del><ins>+    JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(size_t numElements, unsigned elementByteSize);
+    JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(size_t numElements, unsigned elementByteSize);
</ins><span class="cx"> 
</span><span class="cx">     inline void* data();
</span><span class="cx">     inline const void* data() const;
</span><del>-    inline unsigned byteLength() const;
</del><ins>+    inline size_t byteLength() const;
</ins><span class="cx">     
</span><span class="cx">     void makeShared();
</span><span class="cx">     void setSharingMode(ArrayBufferSharingMode);
</span><span class="lines">@@ -137,7 +146,7 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin, double end) const;
</span><span class="cx">     JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin) const;
</span><del>-    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(unsigned begin, unsigned end) const;
</del><ins>+    JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(size_t begin, size_t end) const;
</ins><span class="cx">     
</span><span class="cx">     inline void pin();
</span><span class="cx">     inline void unpin();
</span><span class="lines">@@ -161,12 +170,12 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static Ref<SharedTask<void(void*)>> primitiveGigacageDestructor();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    static Ref<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
-    static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned);
-    static RefPtr<ArrayBuffer> tryCreate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
</del><ins>+    static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
+    static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, size_t);
+    static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
</ins><span class="cx">     ArrayBuffer(ArrayBufferContents&&);
</span><del>-    inline unsigned clampIndex(double index) const;
-    static inline unsigned clampValue(double x, unsigned left, unsigned right);
</del><ins>+    inline size_t clampIndex(double index) const;
+    static inline size_t clampValue(double x, size_t left, size_t right);
</ins><span class="cx"> 
</span><span class="cx">     void notifyDetaching(VM&);
</span><span class="cx"> 
</span><span class="lines">@@ -192,7 +201,7 @@
</span><span class="cx">     return m_contents.data();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned ArrayBuffer::byteLength() const
</del><ins>+size_t ArrayBuffer::byteLength() const
</ins><span class="cx"> {
</span><span class="cx">     return m_contents.sizeInBytes();
</span><span class="cx"> }
</span><span class="lines">@@ -205,7 +214,7 @@
</span><span class="cx"> size_t ArrayBuffer::gcSizeEstimateInBytes() const
</span><span class="cx"> {
</span><span class="cx">     // FIXME: We probably want to scale this by the shared ref count or something.
</span><del>-    return sizeof(ArrayBuffer) + static_cast<size_t>(byteLength());
</del><ins>+    return sizeof(ArrayBuffer) + byteLength();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ArrayBuffer::pin()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayBufferViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -25,18 +25,17 @@
</span><span class="cx"> 
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "ArrayBufferView.h"
</span><del>-#include <wtf/CheckedArithmetic.h>
</del><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> ArrayBufferView::ArrayBufferView(
</span><del>-    RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
</del><ins>+    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
</ins><span class="cx">         : m_byteOffset(byteOffset)
</span><span class="cx">         , m_isDetachable(true)
</span><span class="cx">         , m_byteLength(byteLength)
</span><span class="cx">         , m_buffer(WTFMove(buffer))
</span><span class="cx"> {
</span><del>-    Checked<unsigned, CrashOnOverflow> length(byteOffset);
</del><ins>+    Checked<size_t, CrashOnOverflow> length(byteOffset);
</ins><span class="cx">     length += byteLength;
</span><span class="cx">     RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(length <= m_buffer->byteLength());
</span><span class="cx">     if (m_buffer)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayBufferViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include "TypedArrayType.h"
</span><span class="cx"> #include <algorithm>
</span><span class="cx"> #include <limits.h>
</span><ins>+#include <wtf/CheckedArithmetic.h>
</ins><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="cx"> #include <wtf/RefPtr.h>
</span><span class="cx"> 
</span><span class="lines">@@ -77,7 +78,7 @@
</span><span class="cx"> 
</span><span class="cx">     void* data() const { return baseAddress(); }
</span><span class="cx"> 
</span><del>-    unsigned byteOffset() const
</del><ins>+    size_t byteOffset() const
</ins><span class="cx">     {
</span><span class="cx">         if (isDetached())
</span><span class="cx">             return 0;
</span><span class="lines">@@ -84,7 +85,7 @@
</span><span class="cx">         return m_byteOffset;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned byteLength() const { return m_byteLength; }
</del><ins>+    size_t byteLength() const { return m_byteLength; }
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void setDetachable(bool);
</span><span class="cx">     bool isDetachable() const { return m_isDetachable; }
</span><span class="lines">@@ -92,19 +93,18 @@
</span><span class="cx">     JS_EXPORT_PRIVATE virtual ~ArrayBufferView();
</span><span class="cx"> 
</span><span class="cx">     // Helper to verify byte offset is size aligned.
</span><del>-    static bool verifyByteOffsetAlignment(unsigned byteOffset, size_t size)
</del><ins>+    static bool verifyByteOffsetAlignment(size_t byteOffset, size_t elementSize)
</ins><span class="cx">     {
</span><del>-        return !(byteOffset & (size - 1));
</del><ins>+        return !(byteOffset & (elementSize - 1));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Helper to verify that a given sub-range of an ArrayBuffer is
-    // within range.
-    static bool verifySubRangeLength(const ArrayBuffer& buffer, unsigned byteOffset, unsigned numElements, size_t size)
</del><ins>+    // Helper to verify that a given sub-range of an ArrayBuffer is within range.
+    static bool verifySubRangeLength(const ArrayBuffer& buffer, size_t byteOffset, size_t numElements, unsigned elementSize)
</ins><span class="cx">     {
</span><del>-        unsigned byteLength = buffer.byteLength();
</del><ins>+        size_t byteLength = buffer.byteLength();
</ins><span class="cx">         if (byteOffset > byteLength)
</span><span class="cx">             return false;
</span><del>-        unsigned remainingElements = (byteLength - byteOffset) / size;
</del><ins>+        size_t remainingElements = (byteLength - byteOffset) / static_cast<size_t>(elementSize);
</ins><span class="cx">         if (numElements > remainingElements)
</span><span class="cx">             return false;
</span><span class="cx">         return true;
</span><span class="lines">@@ -113,43 +113,48 @@
</span><span class="cx">     virtual JSArrayBufferView* wrap(JSGlobalObject*, JSGlobalObject*) = 0;
</span><span class="cx">     
</span><span class="cx"> protected:
</span><del>-    JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned byteLength);
</del><ins>+    JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
</ins><span class="cx"> 
</span><del>-    inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
</del><ins>+    inline bool setImpl(ArrayBufferView*, size_t byteOffset);
</ins><span class="cx"> 
</span><del>-    inline bool setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset);
-    inline bool getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset);
</del><ins>+    inline bool setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset);
+    inline bool getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset);
</ins><span class="cx"> 
</span><del>-    inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength);
</del><ins>+    inline bool zeroRangeImpl(size_t byteOffset, size_t rangeByteLength);
</ins><span class="cx"> 
</span><del>-    static inline void calculateOffsetAndLength(
-        int start, int end, unsigned arraySize,
-        unsigned* offset, unsigned* length);
-
</del><span class="cx">     // Input offset is in number of elements from this array's view;
</span><span class="cx">     // output offset is in number of bytes from the underlying buffer's view.
</span><span class="cx">     template <typename T>
</span><span class="cx">     static void clampOffsetAndNumElements(
</span><span class="cx">         const ArrayBuffer& buffer,
</span><del>-        unsigned arrayByteOffset,
-        unsigned *offset,
-        unsigned *numElements)
</del><ins>+        size_t arrayByteOffset,
+        size_t *offset,
+        size_t *numElements)
</ins><span class="cx">     {
</span><del>-        unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
</del><ins>+        size_t maxOffset = (std::numeric_limits<size_t>::max() - arrayByteOffset) / sizeof(T);
</ins><span class="cx">         if (*offset > maxOffset) {
</span><span class="cx">             *offset = buffer.byteLength();
</span><span class="cx">             *numElements = 0;
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-        *offset = arrayByteOffset + *offset * sizeof(T);
-        *offset = std::min(buffer.byteLength(), *offset);
-        unsigned remainingElements = (buffer.byteLength() - *offset) / sizeof(T);
</del><ins>+        CheckedSize adjustedOffset = *offset;
+        adjustedOffset *= sizeof(T);
+        adjustedOffset += arrayByteOffset;
+        if (adjustedOffset.hasOverflowed() || adjustedOffset.value() > buffer.byteLength())
+            *offset = buffer.byteLength();
+        else
+            *offset = adjustedOffset.value();
+        size_t remainingElements = (buffer.byteLength() - *offset) / sizeof(T);
</ins><span class="cx">         *numElements = std::min(remainingElements, *numElements);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned m_byteOffset : 31;
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    uint64_t m_byteOffset : 63;
+#else
+    uint32_t m_byteOffset : 31;
+#endif
</ins><span class="cx">     bool m_isDetachable : 1;
</span><del>-    unsigned m_byteLength;
</del><ins>+    UCPURegister m_byteLength;
</ins><span class="cx"> 
</span><span class="cx">     using BaseAddress = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
</span><span class="cx">     // This is the address of the ArrayBuffer's storage, plus the byte offset.
</span><span class="lines">@@ -160,28 +165,20 @@
</span><span class="cx">     RefPtr<ArrayBuffer> m_buffer;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset)
</del><ins>+bool ArrayBufferView::setImpl(ArrayBufferView* array, size_t byteOffset)
</ins><span class="cx"> {
</span><del>-    if (byteOffset > byteLength()
-        || byteOffset + array->byteLength() > byteLength()
-        || byteOffset + array->byteLength() < byteOffset) {
-        // Out of range offset or overflow
</del><ins>+    if (!isSumSmallerThanOrEqual(byteOffset, array->byteLength(), byteLength()))
</ins><span class="cx">         return false;
</span><del>-    }
-    
</del><ins>+
</ins><span class="cx">     uint8_t* base = static_cast<uint8_t*>(baseAddress());
</span><span class="cx">     memmove(base + byteOffset, array->baseAddress(), array->byteLength());
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset)
</del><ins>+bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset)
</ins><span class="cx"> {
</span><del>-    if (byteOffset > byteLength()
-        || byteOffset + dataByteLength > byteLength()
-        || byteOffset + dataByteLength < byteOffset) {
-        // Out of range offset or overflow
</del><ins>+    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
</ins><span class="cx">         return false;
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     uint8_t* base = static_cast<uint8_t*>(baseAddress());
</span><span class="cx">     memmove(base + byteOffset, data, dataByteLength);
</span><span class="lines">@@ -188,14 +185,10 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset)
</del><ins>+bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset)
</ins><span class="cx"> {
</span><del>-    if (byteOffset > byteLength()
-        || byteOffset + dataByteLength > byteLength()
-        || byteOffset + dataByteLength < byteOffset) {
-        // Out of range offset or overflow
</del><ins>+    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
</ins><span class="cx">         return false;
</span><del>-    }
</del><span class="cx"> 
</span><span class="cx">     const uint8_t* base = static_cast<const uint8_t*>(baseAddress());
</span><span class="cx">     memmove(destination, base + byteOffset, dataByteLength);
</span><span class="lines">@@ -202,39 +195,16 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength)
</del><ins>+bool ArrayBufferView::zeroRangeImpl(size_t byteOffset, size_t rangeByteLength)
</ins><span class="cx"> {
</span><del>-    if (byteOffset > byteLength()
-        || byteOffset + rangeByteLength > byteLength()
-        || byteOffset + rangeByteLength < byteOffset) {
-        // Out of range offset or overflow
</del><ins>+    if (!isSumSmallerThanOrEqual(byteOffset, rangeByteLength, byteLength()))
</ins><span class="cx">         return false;
</span><del>-    }
-    
</del><ins>+
</ins><span class="cx">     uint8_t* base = static_cast<uint8_t*>(baseAddress());
</span><span class="cx">     memset(base + byteOffset, 0, rangeByteLength);
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void ArrayBufferView::calculateOffsetAndLength(
-    int start, int end, unsigned arraySize, unsigned* offset, unsigned* length)
-{
-    if (start < 0)
-        start += arraySize;
-    if (start < 0)
-        start = 0;
-    if (end < 0)
-        end += arraySize;
-    if (end < 0)
-        end = 0;
-    if (static_cast<unsigned>(end) > arraySize)
-        end = arraySize;
-    if (end < start)
-        end = start;
-    *offset = static_cast<unsigned>(start);
-    *length = static_cast<unsigned>(end - start);
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> using JSC::ArrayBufferView;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeAtomicsObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -120,8 +120,7 @@
</span><span class="cx">         accessIndex = accessIndexValue.toIndex(globalObject, "accessIndex");
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, 0);
</span><span class="cx">     }
</span><del>-    
-    ASSERT(typedArrayView->length() <= static_cast<unsigned>(INT_MAX));
</del><ins>+
</ins><span class="cx">     if (accessIndex >= typedArrayView->length()) {
</span><span class="cx">         throwRangeError(globalObject, scope, "Access index out of bounds for atomic access."_s);
</span><span class="cx">         return 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDataViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DataView.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DataView.cpp 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/DataView.cpp    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,13 +32,13 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-DataView::DataView(RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
</del><ins>+DataView::DataView(RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
</ins><span class="cx">     : ArrayBufferView(WTFMove(buffer), byteOffset, byteLength)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Ref<DataView> DataView::create(
</span><del>-    RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned byteLength)
</del><ins>+    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength)
</ins><span class="cx"> {
</span><span class="cx">     return adoptRef(*new DataView(WTFMove(buffer), byteOffset, byteLength));
</span><span class="cx"> }
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> 
</span><span class="cx"> Ref<DataView> DataView::create(RefPtr<ArrayBuffer>&& buffer)
</span><span class="cx"> {
</span><del>-    unsigned byteLength = buffer->byteLength();
</del><ins>+    size_t byteLength = buffer->byteLength();
</ins><span class="cx">     return create(WTFMove(buffer), 0, byteLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDataViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DataView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DataView.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/DataView.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> class DataView final : public ArrayBufferView {
</span><span class="cx"> public:
</span><del>-    JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
</del><ins>+    JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
</ins><span class="cx">     static Ref<DataView> create(RefPtr<ArrayBuffer>&&);
</span><span class="cx">     
</span><span class="cx">     TypedArrayType getType() const final
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx">     JSArrayBufferView* wrap(JSGlobalObject*, JSGlobalObject*) final;
</span><span class="cx">     
</span><span class="cx">     template<typename T>
</span><del>-    T get(unsigned offset, bool littleEndian, bool* status = nullptr)
</del><ins>+    T get(size_t offset, bool littleEndian, bool* status = nullptr)
</ins><span class="cx">     {
</span><span class="cx">         if (status) {
</span><span class="cx">             if (offset + sizeof(T) > byteLength()) {
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template<typename T>
</span><del>-    T read(unsigned& offset, bool littleEndian, bool* status = nullptr)
</del><ins>+    T read(size_t& offset, bool littleEndian, bool* status = nullptr)
</ins><span class="cx">     {
</span><span class="cx">         T result = this->template get<T>(offset, littleEndian, status);
</span><span class="cx">         if (!status || *status)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template<typename T>
</span><del>-    void set(unsigned offset, T value, bool littleEndian, bool* status = nullptr)
</del><ins>+    void set(size_t offset, T value, bool littleEndian, bool* status = nullptr)
</ins><span class="cx">     {
</span><span class="cx">         if (status) {
</span><span class="cx">             if (offset + sizeof(T) > byteLength()) {
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    DataView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned byteLength);
</del><ins>+    DataView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGenericTypedArrayViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,24 +33,24 @@
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> class GenericTypedArrayView final : public ArrayBufferView {
</span><span class="cx"> public:
</span><del>-    static Ref<GenericTypedArrayView> create(unsigned length);
-    static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, unsigned length);
-    static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
-    static RefPtr<GenericTypedArrayView> tryCreate(unsigned length);
-    static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, unsigned length);
-    static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
</del><ins>+    static Ref<GenericTypedArrayView> create(size_t length);
+    static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, size_t length);
+    static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
+    static RefPtr<GenericTypedArrayView> tryCreate(size_t length);
+    static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, size_t length);
+    static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
</ins><span class="cx">     
</span><del>-    static Ref<GenericTypedArrayView> createUninitialized(unsigned length);
-    static RefPtr<GenericTypedArrayView> tryCreateUninitialized(unsigned length);
</del><ins>+    static Ref<GenericTypedArrayView> createUninitialized(size_t length);
+    static RefPtr<GenericTypedArrayView> tryCreateUninitialized(size_t length);
</ins><span class="cx">     
</span><span class="cx">     typename Adaptor::Type* data() const { return static_cast<typename Adaptor::Type*>(baseAddress()); }
</span><span class="cx">     
</span><del>-    bool set(GenericTypedArrayView<Adaptor>* array, unsigned offset)
</del><ins>+    bool set(GenericTypedArrayView<Adaptor>* array, size_t offset)
</ins><span class="cx">     {
</span><span class="cx">         return setImpl(array, offset * sizeof(typename Adaptor::Type));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool setRange(const typename Adaptor::Type* data, size_t count, unsigned offset)
</del><ins>+    bool setRange(const typename Adaptor::Type* data, size_t count, size_t offset)
</ins><span class="cx">     {
</span><span class="cx">         return setRangeImpl(
</span><span class="cx">             reinterpret_cast<const char*>(data),
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">             offset * sizeof(typename Adaptor::Type));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool zeroRange(unsigned offset, size_t count)
</del><ins>+    bool zeroRange(size_t offset, size_t count)
</ins><span class="cx">     {
</span><span class="cx">         return zeroRangeImpl(offset * sizeof(typename Adaptor::Type), count * sizeof(typename Adaptor::Type));
</span><span class="cx">     }
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">     
</span><span class="cx">     void zeroFill() { zeroRange(0, length()); }
</span><span class="cx">     
</span><del>-    unsigned length() const
</del><ins>+    size_t length() const
</ins><span class="cx">     {
</span><span class="cx">         if (isDetached())
</span><span class="cx">             return 0;
</span><span class="lines">@@ -72,25 +72,25 @@
</span><span class="cx">         return byteLength() / sizeof(typename Adaptor::Type);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    typename Adaptor::Type item(unsigned index) const
</del><ins>+    typename Adaptor::Type item(size_t index) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
</span><span class="cx">         return data()[index];
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void set(unsigned index, double value) const
</del><ins>+    void set(size_t index, double value) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
</span><span class="cx">         data()[index] = Adaptor::toNativeFromDouble(value);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void setNative(unsigned index, typename Adaptor::Type value) const
</del><ins>+    void setNative(size_t index, typename Adaptor::Type value) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(index < this->length());
</span><span class="cx">         data()[index] = value;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool getRange(typename Adaptor::Type* data, size_t count, unsigned offset)
</del><ins>+    bool getRange(typename Adaptor::Type* data, size_t count, size_t offset)
</ins><span class="cx">     {
</span><span class="cx">         return getRangeImpl(
</span><span class="cx">             reinterpret_cast<char*>(data),
</span><span class="lines">@@ -98,18 +98,11 @@
</span><span class="cx">             offset * sizeof(typename Adaptor::Type));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool checkInboundData(unsigned offset, size_t count) const
</del><ins>+    bool checkInboundData(size_t offset, size_t count) const
</ins><span class="cx">     {
</span><del>-        unsigned length = this->length();
-        return (offset <= length
-            && offset + count <= length
-            // check overflow
-            && offset + count >= offset);
</del><ins>+        return isSumSmallerThanOrEqual(offset, count, this->length());
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    RefPtr<GenericTypedArrayView> subarray(int start) const;
-    RefPtr<GenericTypedArrayView> subarray(int start, int end) const;
-    
</del><span class="cx">     TypedArrayType getType() const final
</span><span class="cx">     {
</span><span class="cx">         return Adaptor::typeValue;
</span><span class="lines">@@ -118,7 +111,7 @@
</span><span class="cx">     JSArrayBufferView* wrap(JSGlobalObject*, JSGlobalObject*) final;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    GenericTypedArrayView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
</del><ins>+    GenericTypedArrayView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,13 +32,14 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> GenericTypedArrayView<Adaptor>::GenericTypedArrayView(
</span><del>-RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
</del><ins>+RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
</ins><span class="cx">     : ArrayBufferView(WTFMove(buffer), byteOffset, length * sizeof(typename Adaptor::Type))
</span><span class="cx"> {
</span><ins>+    ASSERT((length / sizeof(typename Adaptor::Type)) < std::numeric_limits<size_t>::max());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><del>-Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(unsigned length)
</del><ins>+Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(size_t length)
</ins><span class="cx"> {
</span><span class="cx">     auto result = tryCreate(length);
</span><span class="cx">     RELEASE_ASSERT(result);
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
</span><del>-    const typename Adaptor::Type* array, unsigned length)
</del><ins>+    const typename Adaptor::Type* array, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     auto result = tryCreate(array, length);
</span><span class="cx">     RELEASE_ASSERT(result);
</span><span class="lines">@@ -56,7 +57,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
</span><del>-    RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
</del><ins>+    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     auto result = tryCreate(WTFMove(buffer), byteOffset, length);
</span><span class="cx">     RELEASE_ASSERT(result);
</span><span class="lines">@@ -64,7 +65,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><del>-RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(unsigned length)
</del><ins>+RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(size_t length)
</ins><span class="cx"> {
</span><span class="cx">     auto buffer = ArrayBuffer::tryCreate(length, sizeof(typename Adaptor::Type));
</span><span class="cx">     if (!buffer)
</span><span class="lines">@@ -74,7 +75,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
</span><del>-    const typename Adaptor::Type* array, unsigned length)
</del><ins>+    const typename Adaptor::Type* array, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr<GenericTypedArrayView> result = tryCreate(length);
</span><span class="cx">     if (!result)
</span><span class="lines">@@ -85,7 +86,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
</span><del>-    RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
</del><ins>+    RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     if (!buffer)
</span><span class="cx">         return nullptr;
</span><span class="lines">@@ -100,7 +101,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> Ref<GenericTypedArrayView<Adaptor>>
</span><del>-GenericTypedArrayView<Adaptor>::createUninitialized(unsigned length)
</del><ins>+GenericTypedArrayView<Adaptor>::createUninitialized(size_t length)
</ins><span class="cx"> {
</span><span class="cx">     auto result = tryCreateUninitialized(length);
</span><span class="cx">     RELEASE_ASSERT(result);
</span><span class="lines">@@ -109,7 +110,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> RefPtr<GenericTypedArrayView<Adaptor>>
</span><del>-GenericTypedArrayView<Adaptor>::tryCreateUninitialized(unsigned length)
</del><ins>+GenericTypedArrayView<Adaptor>::tryCreateUninitialized(size_t length)
</ins><span class="cx"> {
</span><span class="cx">     RefPtr<ArrayBuffer> buffer =
</span><span class="cx">         ArrayBuffer::tryCreateUninitialized(length, sizeof(typename Adaptor::Type));
</span><span class="lines">@@ -119,25 +120,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><del>-RefPtr<GenericTypedArrayView<Adaptor>>
-GenericTypedArrayView<Adaptor>::subarray(int start) const
-{
-    return subarray(start, length());
-}
-
-template<typename Adaptor>
-RefPtr<GenericTypedArrayView<Adaptor>>
-GenericTypedArrayView<Adaptor>::subarray(int start, int end) const
-{
-    unsigned offset, length;
-    calculateOffsetAndLength(start, end, this->length(), &offset, &length);
-    ArrayBuffer* buffer = possiblySharedBuffer();
-    ASSERT(buffer);
-    clampOffsetAndNumElements<Adaptor::Type>(*buffer, byteOffset(), &offset, &length);
-    return tryCreate(buffer, offset, length);
-}
-
-template<typename Adaptor>
</del><span class="cx"> JSArrayBufferView* GenericTypedArrayView<Adaptor>::wrap(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject)
</span><span class="cx"> {
</span><span class="cx">     UNUSED_PARAM(lexicalGlobalObject);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> JSArrayBufferView::ConstructionContext::ConstructionContext(
</span><del>-    Structure* structure, uint32_t length, void* vector)
</del><ins>+    Structure* structure, size_t length, void* vector)
</ins><span class="cx">     : m_structure(structure)
</span><span class="cx">     , m_vector(vector, length)
</span><span class="cx">     , m_length(length)
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSArrayBufferView::ConstructionContext::ConstructionContext(
</span><del>-    VM& vm, Structure* structure, uint32_t length, uint32_t elementSize,
</del><ins>+    VM& vm, Structure* structure, size_t length, unsigned elementSize,
</ins><span class="cx">     InitializationMode mode)
</span><span class="cx">     : m_structure(nullptr)
</span><span class="cx">     , m_length(length)
</span><span class="lines">@@ -81,18 +81,18 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Don't allow a typed array to use more than 2GB.
-    if (length > static_cast<unsigned>(INT_MAX) / elementSize)
</del><ins>+    CheckedSize size = length;
+    size *= elementSize;
+    if (size.hasOverflowed() || size > MAX_ARRAY_BUFFER_SIZE)
</ins><span class="cx">         return;
</span><del>-    
-    size_t size = static_cast<size_t>(length) * static_cast<size_t>(elementSize);
-    m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size), length);
</del><ins>+
+    m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size.value()), length);
</ins><span class="cx">     if (!m_vector)
</span><span class="cx">         return;
</span><span class="cx">     if (mode == ZeroFill)
</span><span class="cx">         memset(vector(), 0, size);
</span><span class="cx">     
</span><del>-    vm.heap.reportExtraMemoryAllocated(static_cast<size_t>(length) * elementSize);
</del><ins>+    vm.heap.reportExtraMemoryAllocated(size.value());
</ins><span class="cx">     
</span><span class="cx">     m_structure = structure;
</span><span class="cx">     m_mode = OversizeTypedArray;
</span><span class="lines">@@ -100,7 +100,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSArrayBufferView::ConstructionContext::ConstructionContext(
</span><span class="cx">     VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
</span><del>-    unsigned byteOffset, unsigned length)
</del><ins>+    size_t byteOffset, size_t length)
</ins><span class="cx">     : m_structure(structure)
</span><span class="cx">     , m_length(length)
</span><span class="cx">     , m_mode(WastefulTypedArray)
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSArrayBufferView::ConstructionContext::ConstructionContext(
</span><span class="cx">     Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer,
</span><del>-    unsigned byteOffset, unsigned length, DataViewTag)
</del><ins>+    size_t byteOffset, size_t length, DataViewTag)
</ins><span class="cx">     : m_structure(structure)
</span><span class="cx">     , m_length(length)
</span><span class="cx">     , m_mode(DataViewMode)
</span><span class="lines">@@ -238,9 +238,16 @@
</span><span class="cx">     return ElementSizeData[type - Int8ArrayType];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-unsigned JSArrayBufferView::byteLength() const
</del><ins>+size_t JSArrayBufferView::byteLength() const
</ins><span class="cx"> {
</span><ins>+#if ASSERT_ENABLED
+    Checked<size_t> result = length();
+    result *= elementSize(type());
+    return result.value();
+#else
+    // The absence of overflow is already checked in the constructor, so I only add the extra sanity check when asserts are enabled.
</ins><span class="cx">     return length() * elementSize(type());
</span><ins>+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ArrayBuffer* JSArrayBufferView::slowDownAndWasteMemory()
</span><span class="lines">@@ -267,7 +274,7 @@
</span><span class="cx">     Structure* structure = this->structure(vm);
</span><span class="cx"> 
</span><span class="cx">     RefPtr<ArrayBuffer> buffer;
</span><del>-    unsigned byteLength = this->byteLength();
</del><ins>+    size_t byteLength = this->byteLength();
</ins><span class="cx"> 
</span><span class="cx">     switch (m_mode) {
</span><span class="cx">     case FastTypedArray: {
</span><span class="lines">@@ -315,8 +322,8 @@
</span><span class="cx">     ArrayBuffer* buffer = possiblySharedBuffer();
</span><span class="cx">     if (!buffer)
</span><span class="cx">         return nullptr;
</span><del>-    unsigned byteOffset = this->byteOffset();
-    unsigned length = this->length();
</del><ins>+    size_t byteOffset = this->byteOffset();
+    size_t length = this->length();
</ins><span class="cx">     switch (type()) {
</span><span class="cx"> #define FACTORY(type) \
</span><span class="cx">     case type ## ArrayType: \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -108,7 +108,7 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static constexpr unsigned fastSizeLimit = 1000;
</del><ins>+    static constexpr size_t fastSizeLimit = 1000;
</ins><span class="cx">     using VectorPtr = CagedBarrierPtr<Gigacage::Primitive, void, tagCagedPtr>;
</span><span class="cx"> 
</span><span class="cx">     static void* nullVectorPtr()
</span><span class="lines">@@ -117,10 +117,12 @@
</span><span class="cx">         return null.rawBits();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static size_t sizeOf(uint32_t length, uint32_t elementSize)
</del><ins>+    static size_t sizeOf(size_t length, unsigned elementSize)
</ins><span class="cx">     {
</span><del>-        return (static_cast<size_t>(length) * elementSize + sizeof(EncodedJSValue) - 1)
-            & ~(sizeof(EncodedJSValue) - 1);
</del><ins>+        Checked<size_t> result = length;
+        result *= elementSize;
+        result += sizeof(EncodedJSValue) - 1;
+        return result.value() & ~(sizeof(EncodedJSValue) - 1);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static size_t allocationSize(Checked<size_t> inlineCapacity)
</span><span class="lines">@@ -136,25 +138,25 @@
</span><span class="cx">     public:
</span><span class="cx">         enum InitializationMode { ZeroFill, DontInitialize };
</span><span class="cx">         
</span><del>-        JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, uint32_t length, uint32_t elementSize, InitializationMode = ZeroFill);
</del><ins>+        JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, size_t length, unsigned elementSize, InitializationMode = ZeroFill);
</ins><span class="cx">         
</span><span class="cx">         // This is only for constructing fast typed arrays. It's used by the JIT's slow path.
</span><del>-        ConstructionContext(Structure*, uint32_t length, void* vector);
</del><ins>+        ConstructionContext(Structure*, size_t length, void* vector);
</ins><span class="cx">         
</span><span class="cx">         JS_EXPORT_PRIVATE ConstructionContext(
</span><span class="cx">             VM&, Structure*, RefPtr<ArrayBuffer>&&,
</span><del>-            unsigned byteOffset, unsigned length);
</del><ins>+            size_t byteOffset, size_t length);
</ins><span class="cx">         
</span><span class="cx">         enum DataViewTag { DataView };
</span><span class="cx">         ConstructionContext(
</span><span class="cx">             Structure*, RefPtr<ArrayBuffer>&&,
</span><del>-            unsigned byteOffset, unsigned length, DataViewTag);
</del><ins>+            size_t byteOffset, size_t length, DataViewTag);
</ins><span class="cx">         
</span><span class="cx">         bool operator!() const { return !m_structure; }
</span><span class="cx">         
</span><span class="cx">         Structure* structure() const { return m_structure; }
</span><span class="cx">         void* vector() const { return m_vector.getMayBeNull(m_length); }
</span><del>-        uint32_t length() const { return m_length; }
</del><ins>+        size_t length() const { return m_length; }
</ins><span class="cx">         TypedArrayMode mode() const { return m_mode; }
</span><span class="cx">         Butterfly* butterfly() const { return m_butterfly; }
</span><span class="cx">         
</span><span class="lines">@@ -162,7 +164,7 @@
</span><span class="cx">         Structure* m_structure;
</span><span class="cx">         using VectorType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
</span><span class="cx">         VectorType m_vector;
</span><del>-        uint32_t m_length;
</del><ins>+        size_t m_length;
</ins><span class="cx">         TypedArrayMode m_mode;
</span><span class="cx">         Butterfly* m_butterfly;
</span><span class="cx">     };
</span><span class="lines">@@ -190,11 +192,11 @@
</span><span class="cx">     void* vector() const { return m_vector.getMayBeNull(length()); }
</span><span class="cx">     void* vectorWithoutPACValidation() const { return m_vector.getUnsafe(); }
</span><span class="cx">     
</span><del>-    inline unsigned byteOffset();
-    inline std::optional<unsigned> byteOffsetConcurrently();
</del><ins>+    inline size_t byteOffset();
+    inline std::optional<size_t> byteOffsetConcurrently();
</ins><span class="cx"> 
</span><del>-    unsigned length() const { return m_length; }
-    unsigned byteLength() const;
</del><ins>+    size_t length() const { return m_length; }
+    size_t byteLength() const;
</ins><span class="cx"> 
</span><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="cx">     
</span><span class="lines">@@ -219,7 +221,7 @@
</span><span class="cx">     ArrayBuffer* existingBufferInButterfly();
</span><span class="cx"> 
</span><span class="cx">     VectorPtr m_vector;
</span><del>-    uint32_t m_length;
</del><ins>+    size_t m_length;
</ins><span class="cx">     TypedArrayMode m_mode;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -99,7 +99,7 @@
</span><span class="cx">     ptrdiff_t delta =
</span><span class="cx">         bitwise_cast<uint8_t*>(vectorWithoutPACValidation()) - static_cast<uint8_t*>(buffer->data());
</span><span class="cx"> 
</span><del>-    unsigned result = static_cast<unsigned>(delta);
</del><ins>+    size_t result = static_cast<size_t>(delta);
</ins><span class="cx">     if (requester == Mutator)
</span><span class="cx">         ASSERT(static_cast<ptrdiff_t>(result) == delta);
</span><span class="cx">     else {
</span><span class="lines">@@ -110,14 +110,14 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline unsigned JSArrayBufferView::byteOffset()
</del><ins>+inline size_t JSArrayBufferView::byteOffset()
</ins><span class="cx"> {
</span><del>-    return byteOffsetImpl<Mutator, unsigned>();
</del><ins>+    return byteOffsetImpl<Mutator, size_t>();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline std::optional<unsigned> JSArrayBufferView::byteOffsetConcurrently()
</del><ins>+inline std::optional<size_t> JSArrayBufferView::byteOffsetConcurrently()
</ins><span class="cx"> {
</span><del>-    return byteOffsetImpl<ConcurrentThread, std::optional<unsigned>>();
</del><ins>+    return byteOffsetImpl<ConcurrentThread, std::optional<size_t>>();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline RefPtr<ArrayBufferView> JSArrayBufferView::toWrapped(VM& vm, JSValue value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include <wtf/MathExtras.h>
</span><span class="cx"> #include <wtf/MediaTime.h>
</span><span class="cx"> #include <wtf/Nonmovable.h>
</span><ins>+#include <wtf/StdIntExtras.h>
</ins><span class="cx"> #include <wtf/StdLibExtras.h>
</span><span class="cx"> #include <wtf/TriState.h>
</span><span class="cx"> 
</span><span class="lines">@@ -298,6 +299,7 @@
</span><span class="cx">     int32_t toInt32(JSGlobalObject*) const;
</span><span class="cx">     uint32_t toUInt32(JSGlobalObject*) const;
</span><span class="cx">     uint32_t toIndex(JSGlobalObject*, const char* errorName) const;
</span><ins>+    size_t toTypedArrayIndex(JSGlobalObject*, const char* errorName) const;
</ins><span class="cx">     double toLength(JSGlobalObject*) const;
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE JSValue toBigInt(JSGlobalObject*) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -69,14 +69,47 @@
</span><span class="cx">         throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " cannot be negative")));
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><del>-    if (d > std::numeric_limits<unsigned>::max()) {
</del><ins>+
+    if (isInt32())
+        return asInt32();
+
+    if (d > static_cast<double>(std::numeric_limits<unsigned>::max())) {
</ins><span class="cx">         throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large")));
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RELEASE_AND_RETURN(scope, JSC::toInt32(d));
+}
+
+inline size_t JSValue::toTypedArrayIndex(JSGlobalObject* globalObject, const char* errorName) const
+{
+    VM& vm = getVM(globalObject);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    double d = toNumber(globalObject);
+    RETURN_IF_EXCEPTION(scope, 0);
+    if (d <= -1) {
+        throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " cannot be negative")));
+        return 0;
+    }
+
</ins><span class="cx">     if (isInt32())
</span><span class="cx">         return asInt32();
</span><del>-    RELEASE_AND_RETURN(scope, JSC::toInt32(d));
</del><ins>+
+    if (d > static_cast<double>(MAX_ARRAY_BUFFER_SIZE)) {
+        throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large")));
+        return 0;
+    }
+
+    // All of this monstrosity is just to give the correct result on 1<<32.
+    size_t outputOffset = 0;
+    double inputOffset = 0;
+    size_t int32Max = std::numeric_limits<int32_t>::max();
+    if (d > static_cast<double>(int32Max)) {
+        outputOffset = int32Max;
+        inputOffset = int32Max;
+    }
+    RELEASE_AND_RETURN(scope, outputOffset + static_cast<size_t>(static_cast<uint32_t>(JSC::toInt32(d - inputOffset))));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // https://tc39.es/ecma262/#sec-tointegerorinfinity
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDataViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSDataView.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDataView.cpp       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSDataView.cpp  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> JSDataView* JSDataView::create(
</span><span class="cx">     JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
</span><del>-    unsigned byteOffset, unsigned byteLength)
</del><ins>+    size_t byteOffset, size_t byteLength)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -70,25 +70,25 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, unsigned)
</del><ins>+JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, size_t)
</ins><span class="cx"> {
</span><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JSDataView* JSDataView::create(JSGlobalObject*, Structure*, unsigned)
</del><ins>+JSDataView* JSDataView::create(JSGlobalObject*, Structure*, size_t)
</ins><span class="cx"> {
</span><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JSDataView::set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsigned)
</del><ins>+bool JSDataView::set(JSGlobalObject*, size_t, JSObject*, size_t, size_t)
</ins><span class="cx"> {
</span><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JSDataView::setIndex(JSGlobalObject*, unsigned, JSValue)
</del><ins>+bool JSDataView::setIndex(JSGlobalObject*, size_t, JSValue)
</ins><span class="cx"> {
</span><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><span class="cx">     return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDataViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSDataView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDataView.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSDataView.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -46,15 +46,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE static JSDataView* create(
</span><del>-        JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset,
-        unsigned byteLength);
</del><ins>+        JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);
</ins><span class="cx">     
</span><span class="cx">     // Dummy methods, which don't actually work; these are just in place to
</span><span class="cx">     // placate some template specialization we do elsewhere.
</span><del>-    static JSDataView* createUninitialized(JSGlobalObject*, Structure*, unsigned length);
-    static JSDataView* create(JSGlobalObject*, Structure*, unsigned length);
-    bool set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsigned length);
-    bool setIndex(JSGlobalObject*, unsigned, JSValue);
</del><ins>+    static JSDataView* createUninitialized(JSGlobalObject*, Structure*, size_t length);
+    static JSDataView* create(JSGlobalObject*, Structure*, size_t length);
+    bool set(JSGlobalObject*, size_t, JSObject*, size_t, size_t length);
+    bool setIndex(JSGlobalObject*, size_t, JSValue);
</ins><span class="cx">     
</span><span class="cx">     ArrayBuffer* possiblySharedBuffer() const { return m_buffer; }
</span><span class="cx">     ArrayBuffer* unsharedBuffer() const
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSDataViewPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -136,11 +136,11 @@
</span><span class="cx">     if (!dataView)
</span><span class="cx">         return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s);
</span><span class="cx">     
</span><del>-    unsigned byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
</del><ins>+    size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
</ins><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx">     
</span><span class="cx">     bool littleEndian = false;
</span><del>-    unsigned elementSize = sizeof(typename Adaptor::Type);
</del><ins>+    size_t elementSize = sizeof(typename Adaptor::Type);
</ins><span class="cx">     if (elementSize > 1 && callFrame->argumentCount() >= 2) {
</span><span class="cx">         littleEndian = callFrame->uncheckedArgument(1).toBoolean(globalObject);
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="lines">@@ -149,7 +149,7 @@
</span><span class="cx">     if (dataView->isDetached())
</span><span class="cx">         return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
</span><span class="cx"> 
</span><del>-    unsigned byteLength = dataView->length();
</del><ins>+    size_t byteLength = dataView->length();
</ins><span class="cx">     if (elementSize > byteLength || byteOffset > byteLength - elementSize)
</span><span class="cx">         return throwVMRangeError(globalObject, scope, "Out of bounds access"_s);
</span><span class="cx"> 
</span><span class="lines">@@ -182,7 +182,7 @@
</span><span class="cx">     if (!dataView)
</span><span class="cx">         return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s);
</span><span class="cx">     
</span><del>-    unsigned byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
</del><ins>+    size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");
</ins><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx"> 
</span><span class="cx">     const unsigned dataSize = sizeof(typename Adaptor::Type);
</span><span class="lines">@@ -195,7 +195,7 @@
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx">     
</span><span class="cx">     bool littleEndian = false;
</span><del>-    unsigned elementSize = sizeof(typename Adaptor::Type);
</del><ins>+    size_t elementSize = sizeof(typename Adaptor::Type);
</ins><span class="cx">     if (elementSize > 1 && callFrame->argumentCount() >= 3) {
</span><span class="cx">         littleEndian = callFrame->uncheckedArgument(2).toBoolean(globalObject);
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="lines">@@ -204,7 +204,7 @@
</span><span class="cx">     if (dataView->isDetached())
</span><span class="cx">         return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
</span><span class="cx"> 
</span><del>-    unsigned byteLength = dataView->length();
</del><ins>+    size_t byteLength = dataView->length();
</ins><span class="cx">     if (elementSize > byteLength || byteOffset > byteLength - elementSize)
</span><span class="cx">         return throwVMRangeError(globalObject, scope, "Out of bounds access"_s);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include "JSArrayBufferView.h"
</span><span class="cx"> #include "ThrowScope.h"
</span><span class="cx"> #include "ToNativeFromValue.h"
</span><ins>+#include <wtf/CheckedArithmetic.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -55,10 +56,10 @@
</span><span class="cx"> //     Structure* S     // from JSCell
</span><span class="cx"> //     Butterfly* B     // from JSObject
</span><span class="cx"> //     ElementType* V
</span><del>-//     uint32_t L
</del><ins>+//     size_t L
</ins><span class="cx"> //     TypedArrayMode M
</span><span class="cx"> //
</span><del>-// These fields take up a total of four pointer-width words. FIXME: Make
</del><ins>+// These fields take up a total of five pointer-width words. FIXME: Make
</ins><span class="cx"> // it take less words!
</span><span class="cx"> //
</span><span class="cx"> // B is usually unused but may stored some additional "overflow" data for
</span><span class="lines">@@ -103,14 +104,14 @@
</span><span class="cx"> 
</span><span class="cx">     static constexpr unsigned elementSize = sizeof(typename Adaptor::Type);
</span><span class="cx"> 
</span><del>-    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, unsigned length);
-    static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, unsigned length, void* vector);
-    static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, unsigned length);
-    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned length);
</del><ins>+    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, size_t length);
+    static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, size_t length, void* vector);
+    static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, size_t length);
+    static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length);
</ins><span class="cx">     static JSGenericTypedArrayView* create(VM&, Structure*, RefPtr<typename Adaptor::ViewType>&& impl);
</span><span class="cx">     static JSGenericTypedArrayView* create(Structure*, JSGlobalObject*, RefPtr<typename Adaptor::ViewType>&& impl);
</span><span class="cx">     
</span><del>-    unsigned byteLength() const { return m_length * sizeof(typename Adaptor::Type); }
</del><ins>+    size_t byteLength() const { return m_length * sizeof(typename Adaptor::Type); }
</ins><span class="cx">     size_t byteSize() const { return sizeOf(m_length, sizeof(typename Adaptor::Type)); }
</span><span class="cx">     
</span><span class="cx">     const typename Adaptor::Type* typedVector() const
</span><span class="lines">@@ -122,7 +123,7 @@
</span><span class="cx">         return bitwise_cast<typename Adaptor::Type*>(vector());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool inBounds(unsigned i) const
</del><ins>+    bool inBounds(size_t i) const
</ins><span class="cx">     {
</span><span class="cx">         return i < m_length;
</span><span class="cx">     }
</span><span class="lines">@@ -129,39 +130,39 @@
</span><span class="cx"> 
</span><span class="cx">     // These methods are meant to match indexed access methods that JSObject
</span><span class="cx">     // supports - hence the slight redundancy.
</span><del>-    bool canGetIndexQuickly(unsigned i) const
</del><ins>+    bool canGetIndexQuickly(size_t i) const
</ins><span class="cx">     {
</span><span class="cx">         return inBounds(i) && Adaptor::canConvertToJSQuickly;
</span><span class="cx">     }
</span><del>-    bool canSetIndexQuickly(unsigned i, JSValue value) const
</del><ins>+    bool canSetIndexQuickly(size_t i, JSValue value) const
</ins><span class="cx">     {
</span><span class="cx">         return i < m_length && value.isNumber() && Adaptor::canConvertToJSQuickly;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    typename Adaptor::Type getIndexQuicklyAsNativeValue(unsigned i) const
</del><ins>+    typename Adaptor::Type getIndexQuicklyAsNativeValue(size_t i) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(i < m_length);
</span><span class="cx">         return typedVector()[i];
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    JSValue getIndexQuickly(unsigned i) const
</del><ins>+    JSValue getIndexQuickly(size_t i) const
</ins><span class="cx">     {
</span><span class="cx">         return Adaptor::toJSValue(nullptr, getIndexQuicklyAsNativeValue(i));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void setIndexQuicklyToNativeValue(unsigned i, typename Adaptor::Type value)
</del><ins>+    void setIndexQuicklyToNativeValue(size_t i, typename Adaptor::Type value)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(i < m_length);
</span><span class="cx">         typedVector()[i] = value;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void setIndexQuickly(unsigned i, JSValue value)
</del><ins>+    void setIndexQuickly(size_t i, JSValue value)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(!value.isObject());
</span><span class="cx">         setIndexQuicklyToNativeValue(i, toNativeFromValue<Adaptor>(value));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    bool setIndex(JSGlobalObject* globalObject, unsigned i, JSValue jsValue)
</del><ins>+    bool setIndex(JSGlobalObject* globalObject, size_t i, JSValue jsValue)
</ins><span class="cx">     {
</span><span class="cx">         VM& vm = getVM(globalObject);
</span><span class="cx">         auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -176,9 +177,15 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) { return toNativeFromValue<Adaptor>(globalObject, jsValue); }
</del><ins>+    static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue)
+    {
+        return toNativeFromValue<Adaptor>(globalObject, jsValue);
+    }
</ins><span class="cx"> 
</span><del>-    static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) { return toNativeFromValueWithoutCoercion<Adaptor>(jsValue); }
</del><ins>+    static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue)
+    {
+        return toNativeFromValueWithoutCoercion<Adaptor>(jsValue);
+    }
</ins><span class="cx"> 
</span><span class="cx">     void sort()
</span><span class="cx">     {
</span><span class="lines">@@ -198,21 +205,18 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool canAccessRangeQuickly(unsigned offset, unsigned length)
</del><ins>+    bool canAccessRangeQuickly(size_t offset, size_t length)
</ins><span class="cx">     {
</span><del>-        return offset <= m_length
-            && offset + length <= m_length
-            // check overflow
-            && offset + length >= offset;
</del><ins>+        return isSumSmallerThanOrEqual(offset, length, m_length);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Like canSetQuickly, except: if it returns false, it will throw the
</span><span class="cx">     // appropriate exception.
</span><del>-    bool validateRange(JSGlobalObject*, unsigned offset, unsigned length);
</del><ins>+    bool validateRange(JSGlobalObject*, size_t offset, size_t length);
</ins><span class="cx"> 
</span><span class="cx">     // Returns true if successful, and false on error; if it returns false
</span><span class="cx">     // then it will have thrown an exception.
</span><del>-    bool set(JSGlobalObject*, unsigned offset, JSObject*, unsigned objectOffset, unsigned length, CopyType type = CopyType::Unobservable);
</del><ins>+    bool set(JSGlobalObject*, size_t offset, JSObject*, size_t objectOffset, size_t length, CopyType = CopyType::Unobservable);
</ins><span class="cx">     
</span><span class="cx">     RefPtr<typename Adaptor::ViewType> possiblySharedTypedImpl();
</span><span class="cx">     RefPtr<typename Adaptor::ViewType> unsharedTypedImpl();
</span><span class="lines">@@ -318,8 +322,8 @@
</span><span class="cx">     // Returns true if successful, and false on error; it will throw on error.
</span><span class="cx">     template<typename OtherAdaptor>
</span><span class="cx">     bool setWithSpecificType(
</span><del>-        JSGlobalObject*, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>*,
-        unsigned objectOffset, unsigned length, CopyType);
</del><ins>+        JSGlobalObject*, size_t offset, JSGenericTypedArrayView<OtherAdaptor>*,
+        size_t objectOffset, size_t length, CopyType);
</ins><span class="cx"> 
</span><span class="cx">     // The ECMA 6 spec states that floating point Typed Arrays should have the following ordering:
</span><span class="cx">     //
</span><span class="lines">@@ -349,7 +353,7 @@
</span><span class="cx">     void purifyArray()
</span><span class="cx">     {
</span><span class="cx">         ElementType* array = typedVector();
</span><del>-        for (unsigned i = 0; i < m_length; i++)
</del><ins>+        for (size_t i = 0; i < m_length; i++)
</ins><span class="cx">             array[i] = purifyNaN(array[i]);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewConstructorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h  2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h     2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -143,7 +143,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename ViewClass>
</span><del>-inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, unsigned offset, std::optional<unsigned> lengthOpt)
</del><ins>+inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, size_t offset, std::optional<size_t> lengthOpt)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -157,7 +157,7 @@
</span><span class="cx">             return nullptr;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        unsigned length = 0;
</del><ins>+        size_t length = 0;
</ins><span class="cx">         if (lengthOpt)
</span><span class="cx">             length = lengthOpt.value();
</span><span class="cx">         else {
</span><span class="lines">@@ -182,7 +182,7 @@
</span><span class="cx">     // - A primitive. This creates a new typed array of that length and zero-initializes it.
</span><span class="cx"> 
</span><span class="cx">     if (JSObject* object = jsDynamicCast<JSObject*>(vm, firstValue)) {
</span><del>-        unsigned length;
</del><ins>+        size_t length;
</ins><span class="cx">         JSArrayBuffer* customBuffer = nullptr;
</span><span class="cx"> 
</span><span class="cx">         if (isTypedView(object->classInfo(vm)->typedArrayStorageType)) {
</span><span class="lines">@@ -250,7 +250,7 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    unsigned length = firstValue.toIndex(globalObject, "length");
</del><ins>+    size_t length = firstValue.toTypedArrayIndex(globalObject, "length");
</ins><span class="cx">     RETURN_IF_EXCEPTION(scope, nullptr);
</span><span class="cx">     RELEASE_AND_RETURN(scope, ViewClass::create(globalObject, structure, length));
</span><span class="cx"> }
</span><span class="lines">@@ -275,8 +275,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSValue firstValue = callFrame->uncheckedArgument(0);
</span><del>-    unsigned offset = 0;
-    std::optional<unsigned> length = std::nullopt;
</del><ins>+    size_t offset = 0;
+    std::optional<size_t> length = std::nullopt;
</ins><span class="cx">     if (jsDynamicCast<JSArrayBuffer*>(vm, firstValue) && argCount > 1) {
</span><span class="cx">         offset = callFrame->uncheckedArgument(1).toIndex(globalObject, "byteOffset");
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="lines">@@ -285,7 +285,7 @@
</span><span class="cx">             // If the length value is present but undefined, treat it as missing.
</span><span class="cx">             JSValue lengthValue = callFrame->uncheckedArgument(2);
</span><span class="cx">             if (!lengthValue.isUndefined()) {
</span><del>-                length = lengthValue.toIndex(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length");
</del><ins>+                length = lengthValue.toTypedArrayIndex(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length");
</ins><span class="cx">                 RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h     2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include "JSGenericTypedArrayView.h"
</span><span class="cx"> #include "TypeError.h"
</span><span class="cx"> #include "TypedArrays.h"
</span><ins>+#include <wtf/CheckedArithmetic.h>
</ins><span class="cx"> #include <wtf/text/StringConcatenateNumbers.h>
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -47,7 +48,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
</span><del>-    JSGlobalObject* globalObject, Structure* structure, unsigned length)
</del><ins>+    JSGlobalObject* globalObject, Structure* structure, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -65,7 +66,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createWithFastVector(
</span><del>-    JSGlobalObject* globalObject, Structure* structure, unsigned length, void* vector)
</del><ins>+    JSGlobalObject* globalObject, Structure* structure, size_t length, void* vector)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     ConstructionContext context(structure, length, vector);
</span><span class="lines">@@ -78,7 +79,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><del>-JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, unsigned length)
</del><ins>+JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -99,17 +100,17 @@
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create(
</span><span class="cx">     JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
</span><del>-    unsigned byteOffset, unsigned length)
</del><ins>+    size_t byteOffset, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    size_t size = sizeof(typename Adaptor::Type);
</del><ins>+    size_t elementSize = sizeof(typename Adaptor::Type);
</ins><span class="cx">     ASSERT(buffer);
</span><del>-    if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, size)) {
</del><ins>+    if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, elementSize)) {
</ins><span class="cx">         throwException(globalObject, scope, createRangeError(globalObject, "Length out of range of buffer"));
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><del>-    if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, size)) {
</del><ins>+    if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, elementSize)) {
</ins><span class="cx">         throwException(globalObject, scope, createRangeError(globalObject, "Byte offset is not aligned"));
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="lines">@@ -145,7 +146,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> bool JSGenericTypedArrayView<Adaptor>::validateRange(
</span><del>-    JSGlobalObject* globalObject, unsigned offset, unsigned length)
</del><ins>+    JSGlobalObject* globalObject, size_t offset, size_t length)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -159,8 +160,8 @@
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> template<typename OtherAdaptor>
</span><span class="cx"> bool JSGenericTypedArrayView<Adaptor>::setWithSpecificType(
</span><del>-    JSGlobalObject* globalObject, unsigned offset, JSGenericTypedArrayView<OtherAdaptor>* other,
-    unsigned otherOffset, unsigned length, CopyType type)
</del><ins>+    JSGlobalObject* globalObject, size_t offset, JSGenericTypedArrayView<OtherAdaptor>* other,
+    size_t otherOffset, size_t length, CopyType type)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -218,7 +219,7 @@
</span><span class="cx">         || existingBuffer() != other->existingBuffer()
</span><span class="cx">         || (elementSize == otherElementSize && vector() <= other->vector())
</span><span class="cx">         || type == CopyType::LeftToRight) {
</span><del>-        for (unsigned i = 0; i < length; ++i) {
</del><ins>+        for (size_t i = 0; i < length; ++i) {
</ins><span class="cx">             setIndexQuicklyToNativeValue(
</span><span class="cx">                 offset + i, OtherAdaptor::template convertTo<Adaptor>(
</span><span class="cx">                     other->getIndexQuicklyAsNativeValue(i + otherOffset)));
</span><span class="lines">@@ -228,7 +229,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Now we either have (2B) or (3) - so first we try to cover (2B).
</span><span class="cx">     if (elementSize == otherElementSize) {
</span><del>-        for (unsigned i = length; i--;) {
</del><ins>+        for (size_t i = length; i--;) {
</ins><span class="cx">             setIndexQuicklyToNativeValue(
</span><span class="cx">                 offset + i, OtherAdaptor::template convertTo<Adaptor>(
</span><span class="cx">                     other->getIndexQuicklyAsNativeValue(i + otherOffset)));
</span><span class="lines">@@ -238,11 +239,11 @@
</span><span class="cx">     
</span><span class="cx">     // Fail: we need an intermediate transfer buffer (i.e. case (3)).
</span><span class="cx">     Vector<typename Adaptor::Type, 32> transferBuffer(length);
</span><del>-    for (unsigned i = length; i--;) {
</del><ins>+    for (size_t i = length; i--;) {
</ins><span class="cx">         transferBuffer[i] = OtherAdaptor::template convertTo<Adaptor>(
</span><span class="cx">             other->getIndexQuicklyAsNativeValue(i + otherOffset));
</span><span class="cx">     }
</span><del>-    for (unsigned i = length; i--;)
</del><ins>+    for (size_t i = length; i--;)
</ins><span class="cx">         setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]);
</span><span class="cx">     
</span><span class="cx">     return true;
</span><span class="lines">@@ -250,7 +251,7 @@
</span><span class="cx"> 
</span><span class="cx"> template<typename Adaptor>
</span><span class="cx"> bool JSGenericTypedArrayView<Adaptor>::set(
</span><del>-    JSGlobalObject* globalObject, unsigned offset, JSObject* object, unsigned objectOffset, unsigned length, CopyType type)
</del><ins>+    JSGlobalObject* globalObject, size_t offset, JSObject* object, size_t objectOffset, size_t length, CopyType type)
</ins><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="lines">@@ -257,7 +258,7 @@
</span><span class="cx"> 
</span><span class="cx">     const ClassInfo* ci = object->classInfo(vm);
</span><span class="cx">     if (ci->typedArrayStorageType == Adaptor::typeValue) {
</span><del>-        // The super fast case: we can just memcpy since we're the same type.
</del><ins>+        // The super fast case: we can just memmove since we're the same type.
</ins><span class="cx">         JSGenericTypedArrayView* other = jsCast<JSGenericTypedArrayView*>(object);
</span><span class="cx">         length = std::min(length, other->length());
</span><span class="cx">         
</span><span class="lines">@@ -312,9 +313,11 @@
</span><span class="cx">         if (!success)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><ins>+        // Verify that we won't ever call object->get() with an index of UINT_MAX or more
+        RELEASE_ASSERT(isSumSmallerThanOrEqual(static_cast<uint64_t>(length), static_cast<uint64_t>(objectOffset), static_cast<uint64_t>(std::numeric_limits<unsigned>::max())));
</ins><span class="cx">         // We could optimize this case. But right now, we don't.
</span><del>-        for (unsigned i = 0; i < length; ++i) {
-            JSValue value = object->get(globalObject, i + objectOffset);
</del><ins>+        for (size_t i = 0; i < length; ++i) {
+            JSValue value = object->get(globalObject, static_cast<unsigned>(i + objectOffset));
</ins><span class="cx">             RETURN_IF_EXCEPTION(scope, false);
</span><span class="cx">             bool success = setIndex(globalObject, offset + i, value);
</span><span class="cx">             EXCEPTION_ASSERT(!scope.exception() || !success);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -60,6 +60,7 @@
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+class ArrayProfile;
</ins><span class="cx"> class Exception;
</span><span class="cx"> class GetterSetter;
</span><span class="cx"> class InternalFunction;
</span><span class="lines">@@ -211,10 +212,8 @@
</span><span class="cx">     ALWAYS_INLINE bool putByIndexInline(JSGlobalObject* globalObject, unsigned propertyName, JSValue value, bool shouldThrow)
</span><span class="cx">     {
</span><span class="cx">         VM& vm = getVM(globalObject);
</span><del>-        if (canSetIndexQuickly(propertyName, value)) {
-            setIndexQuickly(vm, propertyName, value);
</del><ins>+        if (trySetIndexQuickly(vm, propertyName, value))
</ins><span class="cx">             return true;
</span><del>-        }
</del><span class="cx">         return methodTable(vm)->putByIndex(this, globalObject, propertyName, value, shouldThrow);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -289,7 +288,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool canGetIndexQuicklyForTypedArray(unsigned) const;
</span><del>-    JSValue getIndexQuicklyForTypedArray(unsigned) const;
</del><ins>+    JSValue getIndexQuicklyForTypedArray(unsigned, ArrayProfile* = nullptr) const;
</ins><span class="cx">     
</span><span class="cx">     bool canGetIndexQuickly(unsigned i) const
</span><span class="cx">     {
</span><span class="lines">@@ -345,14 +344,15 @@
</span><span class="cx">             return JSValue();
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-        
-    JSValue tryGetIndexQuickly(unsigned i) const
</del><ins>+
+    // Uses the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant
+    JSValue tryGetIndexQuickly(unsigned i, ArrayProfile* arrayProfile = nullptr) const
</ins><span class="cx">     {
</span><span class="cx">         const Butterfly* butterfly = this->butterfly();
</span><span class="cx">         switch (indexingType()) {
</span><span class="cx">         case ALL_BLANK_INDEXING_TYPES:
</span><span class="cx">             if (canGetIndexQuicklyForTypedArray(i))
</span><del>-                return getIndexQuicklyForTypedArray(i);
</del><ins>+                return getIndexQuicklyForTypedArray(i, arrayProfile);
</ins><span class="cx">             break;
</span><span class="cx">         case ALL_UNDECIDED_INDEXING_TYPES:
</span><span class="cx">             break;
</span><span class="lines">@@ -411,35 +411,73 @@
</span><span class="cx">         return get(globalObject, i);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool canSetIndexQuicklyForTypedArray(unsigned, JSValue) const;
</del><span class="cx">     void setIndexQuicklyForTypedArray(unsigned, JSValue);
</span><del>-        
-    bool canSetIndexQuickly(unsigned i, JSValue value)
</del><ins>+    void setIndexQuicklyForArrayStorageIndexingType(VM&, unsigned, JSValue);
+
+    // Return true to indicate success
+    // Use the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant
+    bool trySetIndexQuicklyForTypedArray(unsigned, JSValue, ArrayProfile*);
+    bool trySetIndexQuickly(VM& vm, unsigned i, JSValue v, ArrayProfile* arrayProfile = nullptr)
</ins><span class="cx">     {
</span><span class="cx">         Butterfly* butterfly = this->butterfly();
</span><span class="cx">         switch (indexingMode()) {
</span><span class="cx">         case ALL_BLANK_INDEXING_TYPES:
</span><del>-            return canSetIndexQuicklyForTypedArray(i, value);
</del><ins>+            return trySetIndexQuicklyForTypedArray(i, v, arrayProfile);
</ins><span class="cx">         case ALL_UNDECIDED_INDEXING_TYPES:
</span><span class="cx">             return false;
</span><del>-        case ALL_WRITABLE_INT32_INDEXING_TYPES:
-        case ALL_WRITABLE_DOUBLE_INDEXING_TYPES:
-        case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES:
</del><ins>+        case ALL_WRITABLE_INT32_INDEXING_TYPES: {
+            if (i >= butterfly->vectorLength())
+                return false;
+            if (!v.isInt32()) {
+                convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v);
+                return true;
+            }
+            FALLTHROUGH;
+        }
+        case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES: {
+            if (i >= butterfly->vectorLength())
+                return false;
+            butterfly->contiguous().at(this, i).setWithoutWriteBarrier(v);
+            if (i >= butterfly->publicLength())
+                butterfly->setPublicLength(i + 1);
+            vm.heap.writeBarrier(this, v);
+            return true;
+        }
+        case ALL_WRITABLE_DOUBLE_INDEXING_TYPES: {
+            if (i >= butterfly->vectorLength())
+                return false;
+            if (!v.isNumber()) {
+                convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
+                return true;
+            }
+            double value = v.asNumber();
+            if (value != value) {
+                convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
+                return true;
+            }
+            butterfly->contiguousDouble().at(this, i) = value;
+            if (i >= butterfly->publicLength())
+                butterfly->setPublicLength(i + 1);
+            return true;
+        }
</ins><span class="cx">         case NonArrayWithArrayStorage:
</span><span class="cx">         case ArrayWithArrayStorage:
</span><del>-            return i < butterfly->vectorLength();
</del><ins>+            if (i >= butterfly->vectorLength())
+                return false;
+            setIndexQuicklyForArrayStorageIndexingType(vm, i, v);
+            return true;
</ins><span class="cx">         case NonArrayWithSlowPutArrayStorage:
</span><span class="cx">         case ArrayWithSlowPutArrayStorage:
</span><del>-            return i < butterfly->arrayStorage()->vectorLength()
-                && !!butterfly->arrayStorage()->m_vector[i];
</del><ins>+            if (i >= butterfly->arrayStorage()->vectorLength() || !butterfly->arrayStorage()->m_vector[i])
+                return false;
+            setIndexQuicklyForArrayStorageIndexingType(vm, i, v);
+            return true;
</ins><span class="cx">         default:
</span><del>-            if (isCopyOnWrite(indexingMode()))
-                return false;
-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            RELEASE_ASSERT(isCopyOnWrite(indexingMode()));
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-        
</del><ins>+
</ins><span class="cx">     void setIndexQuickly(VM& vm, unsigned i, JSValue v)
</span><span class="cx">     {
</span><span class="cx">         Butterfly* butterfly = m_butterfly.get();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -465,21 +465,15 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool JSObject::canSetIndexQuicklyForTypedArray(unsigned i, JSValue value) const
</del><ins>+inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i, ArrayProfile* arrayProfile) const
</ins><span class="cx"> {
</span><del>-    switch (type()) {
-#define CASE_TYPED_ARRAY_TYPE(name) \
-    case name ## ArrayType :\
-        return jsCast<const JS ## name ## Array *>(this)->canSetIndexQuickly(i, value);
-        FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE)
-#undef CASE_TYPED_ARRAY_TYPE
-    default:
-        return false;
-    }
-}
</del><ins>+#if USE(LARGE_TYPED_ARRAYS)
+    if (i > ArrayProfile::s_smallTypedArrayMaxLength && arrayProfile)
+        arrayProfile->setMayBeLargeTypedArray();
+#else
+    UNUSED_PARAM(arrayProfile);
+#endif
</ins><span class="cx"> 
</span><del>-inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i) const
-{
</del><span class="cx">     switch (type()) {
</span><span class="cx"> #define CASE_TYPED_ARRAY_TYPE(name) \
</span><span class="cx">     case name ## ArrayType : {\
</span><span class="lines">@@ -512,7 +506,50 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> }
</span><del>-    
</del><ins>+
+inline void JSObject::setIndexQuicklyForArrayStorageIndexingType(VM& vm, unsigned i, JSValue v)
+{
+    ArrayStorage* storage = this->butterfly()->arrayStorage();
+    WriteBarrier<Unknown>& x = storage->m_vector[i];
+    JSValue old = x.get();
+    x.set(vm, this, v);
+    if (!old) {
+        ++storage->m_numValuesInVector;
+        if (i >= storage->length())
+            storage->setLength(i + 1);
+    }
+}
+
+inline bool JSObject::trySetIndexQuicklyForTypedArray(unsigned i, JSValue v, ArrayProfile* arrayProfile)
+{
+    switch (type()) {
+#if USE(LARGE_TYPED_ARRAYS)
+#define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \
+        if ((i > ArrayProfile::s_smallTypedArrayMaxLength) && arrayProfile)\
+            arrayProfile->setMayBeLargeTypedArray();\
+    } while (false)
+#else
+#define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \
+    UNUSED_PARAM(arrayProfile);\
+    } while (false)
+#endif
+#define CASE_TYPED_ARRAY_TYPE(name) \
+    case name ## ArrayType : { \
+        auto* typedArray = jsCast<JS ## name ## Array *>(this);\
+        if (!typedArray->canSetIndexQuickly(i, v))\
+            return false;\
+        typedArray->setIndexQuickly(i, v);\
+        UPDATE_ARRAY_PROFILE(i, arrayProfile);\
+        return true;\
+    }
+    FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE)
+#undef CASE_TYPED_ARRAY_TYPE
+#undef UPDATE_ARRAY_PROFILE
+    default:
+        return false;
+    }
+}
+
</ins><span class="cx"> inline void JSObject::validatePutOwnDataProperty(VM& vm, PropertyName propertyName, JSValue value)
</span><span class="cx"> {
</span><span class="cx"> #if ASSERT_ENABLED
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Operations.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Operations.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/runtime/Operations.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -898,8 +898,8 @@
</span><span class="cx"> {
</span><span class="cx">     if (base->isObject()) {
</span><span class="cx">         JSObject* object = asObject(base);
</span><del>-        if (object->canGetIndexQuickly(index))
-            return JSValue::encode(object->getIndexQuickly(index));
</del><ins>+        if (JSValue result = object->tryGetIndexQuickly(index))
+            return JSValue::encode(result);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isJSString(base) && asString(base)->canGetIndex(index))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmPageCounth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmPageCount.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmPageCount.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/JavaScriptCore/wasm/WasmPageCount.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -27,6 +27,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(WEBASSEMBLY)
</span><span class="cx"> 
</span><ins>+#include "ArrayBuffer.h"
+
</ins><span class="cx"> #include <limits.h>
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -96,7 +98,7 @@
</span><span class="cx"> 
</span><span class="cx">     static constexpr uint32_t pageSize = 64 * KB;
</span><span class="cx"> private:
</span><del>-    static constexpr uint32_t maxPageCount = static_cast<uint32_t>((1ull << 32) / pageSize);
</del><ins>+    static constexpr uint32_t maxPageCount = static_cast<uint32_t>(MAX_ARRAY_BUFFER_SIZE / static_cast<uint64_t>(pageSize));
</ins><span class="cx"> 
</span><span class="cx">     uint32_t m_pageCount;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WTF/ChangeLog  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2021-10-16  Robin Morisset  <rmorisset@apple.com>
+
+        Allow WASM to use up to 4GB
+        https://bugs.webkit.org/show_bug.cgi?id=229353
+        rdar://81603447
+
+        Reviewed by Yusuke Suzuki.
+
+        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):
+
</ins><span class="cx"> 2021-10-16  Tim Horton  <timothy_horton@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, reverting r284143.
</span></span></pre></div>
<a id="trunkSourceWTFwtfCheckedArithmetich"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CheckedArithmetic.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CheckedArithmetic.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WTF/wtf/CheckedArithmetic.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -144,7 +144,7 @@
</span><span class="cx"> 
</span><span class="cx"> template <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;
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, false> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // Same signedness so implicit type conversion will always increase precision to widest type.
</span><span class="cx">         return value <= std::numeric_limits<Target>::max();
</span><span class="lines">@@ -151,7 +151,7 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, true> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // Same signedness so implicit type conversion will always increase precision to widest type.
</span><span class="cx">         return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max();
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, true> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // When converting value to unsigned Source, value will become a big value if value is negative.
</span><span class="cx">         // Casted value will become bigger than Target::max as Source is bigger than Target.
</span><span class="lines">@@ -168,7 +168,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, false> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // The unsigned Source type has greater precision than the target so max(Target) -> Source will widen.
</span><span class="cx">         return value <= static_cast<Source>(std::numeric_limits<Target>::max());
</span><span class="lines">@@ -176,7 +176,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, false> {
</span><del>-    static bool inBounds(Source)
</del><ins>+    static bool constexpr inBounds(Source)
</ins><span class="cx">     {
</span><span class="cx">         // Same sign, greater or same precision.
</span><span class="cx">         return true;
</span><span class="lines">@@ -184,7 +184,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, true> {
</span><del>-    static bool inBounds(Source)
</del><ins>+    static bool constexpr inBounds(Source)
</ins><span class="cx">     {
</span><span class="cx">         // Same sign, greater or same precision.
</span><span class="cx">         return true;
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, false> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // Target is signed with greater or same precision. If strictly greater, it is always safe.
</span><span class="cx">         if (sizeof(Target) > sizeof(Source))
</span><span class="lines">@@ -202,7 +202,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, true> {
</span><del>-    static bool inBounds(Source value)
</del><ins>+    static bool constexpr inBounds(Source value)
</ins><span class="cx">     {
</span><span class="cx">         // Target is unsigned with greater precision.
</span><span class="cx">         return value >= 0;
</span><span class="lines">@@ -209,12 +209,12 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-template <typename Target, typename Source> static inline bool isInBounds(Source value)
</del><ins>+template <typename Target, typename Source> static inline constexpr bool isInBounds(Source value)
</ins><span class="cx"> {
</span><span class="cx">     return BoundsChecker<Target, Source>::inBounds(value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template <typename Target, typename Source> static inline bool convertSafely(Source input, Target& output)
</del><ins>+template <typename Target, typename Source> static inline constexpr bool convertSafely(Source input, Target& output)
</ins><span class="cx"> {
</span><span class="cx">     if (!isInBounds<Target>(input))
</span><span class="cx">         return false;
</span><span class="lines">@@ -996,8 +996,15 @@
</span><span class="cx">     return checkedProduct<T>(args...).hasOverflowed();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template<typename T> bool isSumSmallerThanOrEqual(T a, T b, T bound)
+{
+    Checked<T, RecordOverflow> sum = a;
+    sum += b;
+    return !sum.hasOverflowed() && sum.value() <= bound;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> using WTF::AssertNoOverflow;
</span><span class="cx"> using WTF::Checked;
</span><span class="cx"> using WTF::CheckedState;
</span><span class="lines">@@ -1017,3 +1024,4 @@
</span><span class="cx"> using WTF::isInBounds;
</span><span class="cx"> using WTF::productOverflows;
</span><span class="cx"> using WTF::sumOverflows;
</span><ins>+using WTF::isSumSmallerThanOrEqual;
</ins></span></pre></div>
<a id="trunkSourceWTFwtfPlatformUseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PlatformUse.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PlatformUse.h       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WTF/wtf/PlatformUse.h  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -141,6 +141,15 @@
</span><span class="cx"> #define USE_JSVALUE32_64 1
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+// FIXME: this should instead be based on SIZE_MAX == UINT64_MAX
+// But this requires including <cstdint> and Platform.h is included in all kind of weird places, including non-cpp files
+// And in practice CPU(ADDRESS64) is equivalent on all platforms we support (verified by static_asserts in ArrayBuffer.h)
+#if CPU(ADDRESS64)
+#define USE_LARGE_TYPED_ARRAYS 1
+#else
+#define USE_LARGE_TYPED_ARRAYS 0
+#endif
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> /* FIXME: Enable BIGINT32 optimization again after we ensure Speedometer2 and JetStream2 regressions are fixed. */
</span><span class="cx"> /* https://bugs.webkit.org/show_bug.cgi?id=214777 */
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/ChangeLog      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2021-10-16  Robin Morisset  <rmorisset@apple.com>
+
+        Allow WASM to use up to 4GB
+        https://bugs.webkit.org/show_bug.cgi?id=229353
+        rdar://81603447
+
+        Reviewed by Yusuke Suzuki.
+
+        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:
+
</ins><span class="cx"> 2021-10-16  Alan Bujtas  <zalan@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [LFC][IFC] Adjust the logical left side of the line with line spanning inline boxes
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioAudioBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp    2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp       2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -198,7 +198,7 @@
</span><span class="cx">     if (bufferOffset >= dataLength)
</span><span class="cx">         return { };
</span><span class="cx">     
</span><del>-    unsigned count = dataLength - bufferOffset;
</del><ins>+    size_t count = dataLength - bufferOffset;
</ins><span class="cx">     count = std::min(destination.get().length(), count);
</span><span class="cx">     
</span><span class="cx">     const float* src = channelData->data();
</span><span class="lines">@@ -226,7 +226,7 @@
</span><span class="cx">     if (bufferOffset >= dataLength)
</span><span class="cx">         return { };
</span><span class="cx">     
</span><del>-    unsigned count = dataLength - bufferOffset;
</del><ins>+    size_t count = dataLength - bufferOffset;
</ins><span class="cx">     count = std::min(source.get().length(), count);
</span><span class="cx">     
</span><span class="cx">     const float* src = source->data();
</span></span></pre></div>
<a id="trunkSourceWebCoreModuleswebaudioRealtimeAnalysercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -196,8 +196,9 @@
</span><span class="cx">     doFFTAnalysisIfNecessary();
</span><span class="cx">     
</span><span class="cx">     // Convert from linear magnitude to unsigned-byte decibels.
</span><del>-    unsigned sourceLength = magnitudeBuffer().size();
-    size_t length = std::min(sourceLength, destinationArray.length());
</del><ins>+    size_t sourceLength = magnitudeBuffer().size();
+    size_t destinationLength = destinationArray.length();
+    size_t length = std::min(sourceLength, destinationLength);
</ins><span class="cx">     if (length > 0) {
</span><span class="cx">         const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 / (m_maxDecibels - m_minDecibels);
</span><span class="cx">         const double minDecibels = m_minDecibels;
</span><span class="lines">@@ -227,8 +228,9 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     
</span><del>-    unsigned fftSize = this->fftSize();
-    size_t length = std::min(fftSize, destinationArray.length());
</del><ins>+    size_t destinationLength = destinationArray.length();
+    size_t fftSize = this->fftSize();
+    size_t length = std::min(fftSize, destinationLength);
</ins><span class="cx">     if (length > 0) {
</span><span class="cx">         bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize;
</span><span class="cx">         ASSERT(isInputBufferGood);
</span><span class="lines">@@ -251,8 +253,9 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx"> 
</span><del>-    unsigned fftSize = this->fftSize();
-    size_t length = std::min(fftSize, destinationArray.length());
</del><ins>+    size_t destinationLength = destinationArray.length();
+    size_t fftSize = this->fftSize();
+    size_t length = std::min(fftSize, destinationLength);
</ins><span class="cx">     if (length > 0) {
</span><span class="cx">         bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize;
</span><span class="cx">         ASSERT(isInputBufferGood);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsSerializedScriptValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp       2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp  2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx"> #include <JavaScriptCore/WasmModule.h>
</span><span class="cx"> #include <JavaScriptCore/YarrFlags.h>
</span><span class="cx"> #include <limits>
</span><ins>+#include <wtf/CheckedArithmetic.h>
</ins><span class="cx"> #include <wtf/CompletionHandler.h>
</span><span class="cx"> #include <wtf/MainThread.h>
</span><span class="cx"> #include <wtf/RunLoop.h>
</span><span class="lines">@@ -342,8 +343,9 @@
</span><span class="cx">  * Version 7. added support for File's lastModified attribute.
</span><span class="cx">  * Version 8. added support for ImageData's colorSpace attribute.
</span><span class="cx">  * Version 9. added support for ImageBitmap color space.
</span><ins>+ * Version 10. changed the length (and offsets) of ArrayBuffers (and ArrayBufferViews) from 32 to 64 bits
</ins><span class="cx">  */
</span><del>-static const unsigned CurrentVersion = 9;
</del><ins>+static const unsigned CurrentVersion = 10;
</ins><span class="cx"> static const unsigned TerminatorTag = 0xFFFFFFFF;
</span><span class="cx"> static const unsigned StringPoolTag = 0xFFFFFFFE;
</span><span class="cx"> static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
</span><span class="lines">@@ -399,7 +401,7 @@
</span><span class="cx">  *    | ObjectReference
</span><span class="cx">  *    | MessagePortReferenceTag <value:uint32_t>
</span><span class="cx">  *    | ArrayBuffer
</span><del>- *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
</del><ins>+ *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint64_t> <byteLength:uint64_t> (ArrayBuffer | ObjectReference)
</ins><span class="cx">  *    | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
</span><span class="cx">  *    | DOMPoint
</span><span class="cx">  *    | DOMRect
</span><span class="lines">@@ -463,7 +465,7 @@
</span><span class="cx">  *    ObjectReferenceTag <opIndex:IndexType>
</span><span class="cx">  *
</span><span class="cx">  * ArrayBuffer :-
</span><del>- *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
</del><ins>+ *    ArrayBufferTag <length:uint64_t> <contents:byte{length}>
</ins><span class="cx">  *    ArrayBufferTransferTag <value:uint32_t>
</span><span class="cx">  *    SharedArrayBufferTag <value:uint32_t>
</span><span class="cx">  *
</span><span class="lines">@@ -910,7 +912,6 @@
</span><span class="cx"> #if USE(BIGINT32)
</span><span class="cx">     void dumpBigInt32Data(int32_t integer)
</span><span class="cx">     {
</span><del>-        static_assert(sizeof(uint64_t) == sizeof(unsigned long long));
</del><span class="cx">         write(static_cast<uint8_t>(integer < 0));
</span><span class="cx">         if (!integer) {
</span><span class="cx">             write(static_cast<uint32_t>(0)); // Length-in-uint64_t
</span><span class="lines">@@ -920,18 +921,17 @@
</span><span class="cx">         int64_t value = static_cast<int64_t>(integer);
</span><span class="cx">         if (value < 0)
</span><span class="cx">             value = -value;
</span><del>-        write(static_cast<unsigned long long>(value));
</del><ins>+        write(static_cast<uint64_t>(value));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void dumpHeapBigIntData(JSBigInt* bigInt)
</span><span class="cx">     {
</span><del>-        static_assert(sizeof(uint64_t) == sizeof(unsigned long long));
</del><span class="cx">         write(static_cast<uint8_t>(bigInt->sign()));
</span><span class="cx">         if constexpr (sizeof(JSBigInt::Digit) == sizeof(uint64_t)) {
</span><span class="cx">             write(static_cast<uint32_t>(bigInt->length()));
</span><span class="cx">             for (unsigned index = 0; index < bigInt->length(); ++index)
</span><del>-                write(static_cast<unsigned long long>(bigInt->digit(index)));
</del><ins>+                write(static_cast<uint64_t>(bigInt->digit(index)));
</ins><span class="cx">         } else {
</span><span class="cx">             ASSERT(sizeof(JSBigInt::Digit) == sizeof(uint32_t));
</span><span class="cx">             uint32_t lengthInUint64 = bigInt->length() / 2;
</span><span class="lines">@@ -944,12 +944,12 @@
</span><span class="cx">                     value = bigInt->digit(index);
</span><span class="cx">                 else {
</span><span class="cx">                     value = (static_cast<uint64_t>(bigInt->digit(index)) << 32) | value;
</span><del>-                    write(static_cast<unsigned long long>(value));
</del><ins>+                    write(static_cast<uint64_t>(value));
</ins><span class="cx">                     value = 0;
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             if (bigInt->length() & 0x1)
</span><del>-                write(static_cast<unsigned long long>(value));
</del><ins>+                write(static_cast<uint64_t>(value));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -998,8 +998,10 @@
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj);
</span><del>-        write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
-        write(static_cast<uint32_t>(arrayBufferView->byteLength()));
</del><ins>+        uint64_t byteOffset = arrayBufferView->byteOffset();
+        write(byteOffset);
+        uint64_t byteLength = arrayBufferView->byteLength();
+        write(byteLength);
</ins><span class="cx">         RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer();
</span><span class="cx">         if (!arrayBuffer) {
</span><span class="cx">             code = SerializationReturnCode::ValidationError;
</span><span class="lines">@@ -1131,8 +1133,13 @@
</span><span class="cx">         write(static_cast<double>(buffer->resolutionScale()));
</span><span class="cx">         write(buffer->colorSpace());
</span><span class="cx"> 
</span><del>-        write(static_cast<uint32_t>(arrayBuffer->byteLength()));
-        write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
</del><ins>+        CheckedUint32 byteLength = arrayBuffer->byteLength();
+        if (byteLength.hasOverflowed()) {
+            code = SerializationReturnCode::ValidationError;
+            return;
+        }
+        write(byteLength);
+        write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
</span><span class="lines">@@ -1256,7 +1263,9 @@
</span><span class="cx">                 m_blobHandles.append(blob->handle());
</span><span class="cx">                 write(blob->url().string());
</span><span class="cx">                 write(blob->type());
</span><del>-                write(blob->size());
</del><ins>+                static_assert(sizeof(uint64_t) == sizeof(decltype(blob->size())));
+                uint64_t size = blob->size();
+                write(size);
</ins><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             if (auto* data = JSImageData::toWrapped(vm, obj)) {
</span><span class="lines">@@ -1263,8 +1272,13 @@
</span><span class="cx">                 write(ImageDataTag);
</span><span class="cx">                 write(data->width());
</span><span class="cx">                 write(data->height());
</span><del>-                write(data->data().length());
-                write(data->data().data(), data->data().length());
</del><ins>+                CheckedUint32 dataLength = data->data().length();
+                if (dataLength.hasOverflowed()) {
+                    code = SerializationReturnCode::DataCloneError;
+                    return true;
+                }
+                write(dataLength);
+                write(data->data().data(), dataLength);
</ins><span class="cx">                 write(data->colorSpace());
</span><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="lines">@@ -1311,8 +1325,9 @@
</span><span class="cx">                 }
</span><span class="cx">                 
</span><span class="cx">                 write(ArrayBufferTag);
</span><del>-                write(arrayBuffer->byteLength());
-                write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
</del><ins>+                uint64_t byteLength = arrayBuffer->byteLength();
+                write(byteLength);
+                write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength);
</ins><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             if (obj->inherits<JSArrayBufferView>(vm)) {
</span><span class="lines">@@ -1502,7 +1517,7 @@
</span><span class="cx">         writeLittleEndian(m_buffer, i);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void write(unsigned long long i)
</del><ins>+    void write(uint64_t i)
</ins><span class="cx">     {
</span><span class="cx">         writeLittleEndian(m_buffer, i);
</span><span class="cx">     }
</span><span class="lines">@@ -2391,7 +2406,7 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool read(unsigned long long& i)
</del><ins>+    bool read(uint64_t& i)
</ins><span class="cx">     {
</span><span class="cx">         return readLittleEndian(i);
</span><span class="cx">     }
</span><span class="lines">@@ -2555,9 +2570,10 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
</del><ins>+    template<typename LengthType>
+    bool readArrayBufferImpl(RefPtr<ArrayBuffer>& arrayBuffer)
</ins><span class="cx">     {
</span><del>-        uint32_t length;
</del><ins>+        LengthType length;
</ins><span class="cx">         if (!read(length))
</span><span class="cx">             return false;
</span><span class="cx">         if (m_ptr + length > m_end)
</span><span class="lines">@@ -2569,15 +2585,23 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
</del><ins>+    bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer)
</ins><span class="cx">     {
</span><ins>+        if (m_version < 10)
+            return readArrayBufferImpl<uint32_t>(arrayBuffer);
+        return readArrayBufferImpl<uint64_t>(arrayBuffer);
+    }
+
+    template <typename LengthType>
+    bool readArrayBufferViewImpl(VM& vm, JSValue& arrayBufferView)
+    {
</ins><span class="cx">         ArrayBufferViewSubtag arrayBufferViewSubtag;
</span><span class="cx">         if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
</span><span class="cx">             return false;
</span><del>-        uint32_t byteOffset;
</del><ins>+        LengthType byteOffset;
</ins><span class="cx">         if (!read(byteOffset))
</span><span class="cx">             return false;
</span><del>-        uint32_t byteLength;
</del><ins>+        LengthType byteLength;
</ins><span class="cx">         if (!read(byteLength))
</span><span class="cx">             return false;
</span><span class="cx">         JSObject* arrayBufferObj = asObject(readTerminal());
</span><span class="lines">@@ -2587,7 +2611,7 @@
</span><span class="cx">         unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
</span><span class="cx">         if (!elementSize)
</span><span class="cx">             return false;
</span><del>-        unsigned length = byteLength / elementSize;
</del><ins>+        LengthType length = byteLength / elementSize;
</ins><span class="cx">         if (length * elementSize != byteLength)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="lines">@@ -2634,6 +2658,13 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
+    {
+        if (m_version < 10)
+            return readArrayBufferViewImpl<uint32_t>(vm, arrayBufferView);
+        return readArrayBufferViewImpl<uint64_t>(vm, arrayBufferView);
+    }
+
</ins><span class="cx">     bool read(Vector<uint8_t>& result)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(result.isEmpty());
</span><span class="lines">@@ -3345,7 +3376,7 @@
</span><span class="cx">         auto colorSpace = DestinationColorSpace::SRGB();
</span><span class="cx">         RefPtr<ArrayBuffer> arrayBuffer;
</span><span class="cx"> 
</span><del>-        if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBuffer(arrayBuffer)) {
</del><ins>+        if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBufferImpl<uint32_t>(arrayBuffer)) {
</ins><span class="cx">             fail();
</span><span class="cx">             return JSValue();
</span><span class="cx">         }
</span><span class="lines">@@ -3411,8 +3442,7 @@
</span><span class="cx"> #if USE(BIGINT32)
</span><span class="cx">         static_assert(sizeof(JSBigInt::Digit) == sizeof(uint64_t));
</span><span class="cx">         if (lengthInUint64 == 1) {
</span><del>-            static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
-            unsigned long long digit64 = 0;
</del><ins>+            uint64_t digit64 = 0;
</ins><span class="cx">             if (!read(digit64))
</span><span class="cx">                 return JSValue();
</span><span class="cx">             if (sign) {
</span><span class="lines">@@ -3447,8 +3477,7 @@
</span><span class="cx">                 return JSValue();
</span><span class="cx">             }
</span><span class="cx">             for (uint32_t index = 0; index < lengthInUint64; ++index) {
</span><del>-                static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
-                unsigned long long digit64 = 0;
</del><ins>+                uint64_t digit64 = 0;
</ins><span class="cx">                 if (!read(digit64))
</span><span class="cx">                     return JSValue();
</span><span class="cx">                 bigInt->setDigit(index, digit64);
</span><span class="lines">@@ -3461,8 +3490,7 @@
</span><span class="cx">                 return JSValue();
</span><span class="cx">             }
</span><span class="cx">             for (uint32_t index = 0; index < lengthInUint64; ++index) {
</span><del>-                static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
-                unsigned long long digit64 = 0;
</del><ins>+                uint64_t digit64 = 0;
</ins><span class="cx">                 if (!read(digit64))
</span><span class="cx">                     return JSValue();
</span><span class="cx">                 bigInt->setDigit(index * 2, static_cast<uint32_t>(digit64));
</span><span class="lines">@@ -3618,7 +3646,7 @@
</span><span class="cx">             CachedStringRef type;
</span><span class="cx">             if (!readStringData(type))
</span><span class="cx">                 return JSValue();
</span><del>-            unsigned long long size = 0;
</del><ins>+            uint64_t size = 0;
</ins><span class="cx">             if (!read(size))
</span><span class="cx">                 return JSValue();
</span><span class="cx">             if (!m_canCreateDOMObject)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsSerializedScriptValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.h 2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.h    2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -167,7 +167,7 @@
</span><span class="cx">     if (hasArray) {
</span><span class="cx">         encoder << static_cast<uint64_t>(m_arrayBufferContentsArray->size());
</span><span class="cx">         for (const auto &arrayBufferContents : *m_arrayBufferContentsArray) {
</span><del>-            encoder << arrayBufferContents.sizeInBytes();
</del><ins>+            encoder << static_cast<uint64_t>(arrayBufferContents.sizeInBytes());
</ins><span class="cx">             encoder.encodeFixedLengthData(static_cast<const uint8_t*>(arrayBufferContents.data()), arrayBufferContents.sizeInBytes(), 1);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -199,9 +199,12 @@
</span><span class="cx"> 
</span><span class="cx">         arrayBufferContentsArray = makeUnique<ArrayBufferContentsArray>();
</span><span class="cx">         while (arrayLength--) {
</span><del>-            unsigned bufferSize;
</del><ins>+            uint64_t bufferSize;
</ins><span class="cx">             if (!decoder.decode(bufferSize))
</span><span class="cx">                 return nullptr;
</span><ins>+            CheckedSize checkedBufferSize = bufferSize;
+            if (checkedBufferSize.hasOverflowed())
+                return nullptr;
</ins><span class="cx">             if (!decoder.template bufferIsLargeEnoughToContain<uint8_t>(bufferSize))
</span><span class="cx">                 return nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -212,7 +215,7 @@
</span><span class="cx">                 Gigacage::free(Gigacage::Primitive, buffer);
</span><span class="cx">                 return nullptr;
</span><span class="cx">             }
</span><del>-            arrayBufferContentsArray->append({ buffer, bufferSize, ArrayBuffer::primitiveGigacageDestructor() });
</del><ins>+            arrayBufferContentsArray->append({ buffer, checkedBufferSize, ArrayBuffer::primitiveGigacageDestructor() });
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorefileapiNetworkSendQueuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp        2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp   2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -68,7 +68,9 @@
</span><span class="cx"> 
</span><span class="cx">     auto byteLength = blob.size();
</span><span class="cx">     if (!byteLength) {
</span><del>-        enqueue(JSC::ArrayBuffer::create(0U, 1), 0, 0);
</del><ins>+        // The cast looks weird, but is required for the overloading resolution to succeed.
+        // Without it, there is an ambiguity where ArrayBuffer::create(const void* source, size_t byteLength) could be called instead.
+        enqueue(JSC::ArrayBuffer::create(static_cast<size_t>(0U), 1), 0, 0);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     auto blobLoader = makeUniqueRef<BlobLoader>([this](BlobLoader&) {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsPixelBuffercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp   2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp      2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -74,6 +74,8 @@
</span><span class="cx">     auto bufferSize = computeBufferSize(format, size);
</span><span class="cx">     if (bufferSize.hasOverflowed())
</span><span class="cx">         return std::nullopt;
</span><ins>+    if (bufferSize > std::numeric_limits<int32_t>::max())
+        return std::nullopt;
</ins><span class="cx">     auto pixelArray = Uint8ClampedArray::tryCreateUninitialized(bufferSize);
</span><span class="cx">     if (!pixelArray)
</span><span class="cx">         return std::nullopt;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsisoISOBoxh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/iso/ISOBox.h (284329 => 284330)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/iso/ISOBox.h      2021-10-17 03:58:51 UTC (rev 284329)
+++ trunk/Source/WebCore/platform/graphics/iso/ISOBox.h 2021-10-17 04:00:16 UTC (rev 284330)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include "FourCC.h"
</span><span class="cx"> #include <wtf/Forward.h>
</span><ins>+#include <wtf/StdIntExtras.h>
</ins><span class="cx"> #include <wtf/TypeCasts.h>
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -63,7 +64,10 @@
</span><span class="cx">     static bool checkedRead(R& returnValue, V& view, unsigned& offset, Endianness endianness)
</span><span class="cx">     {
</span><span class="cx">         bool readStatus = false;
</span><del>-        T value = view.template read<T>(offset, endianness == LittleEndian, &readStatus);
</del><ins>+        size_t actualOffset = offset;
+        T value = view.template read<T>(actualOffset, endianness == LittleEndian, &readStatus);
+        RELEASE_ASSERT(isInBounds<uint32_t>(actualOffset));
+        offset = actualOffset;
</ins><span class="cx">         if (!readStatus)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>