Changeset 284330 in webkit
- Timestamp:
- Oct 16, 2021 9:00:16 PM (9 months ago)
- Location:
- trunk
- Files:
-
- 3 added
- 91 edited
-
JSTests/ChangeLog (modified) (1 diff)
-
JSTests/stress/big-wasm-memory-grow-no-max.js (modified) (2 diffs)
-
JSTests/stress/big-wasm-memory-grow.js (modified) (2 diffs)
-
JSTests/stress/big-wasm-memory.js (modified) (2 diffs)
-
JSTests/stress/typed-array-always-large.js (added)
-
JSTests/stress/typed-array-eventually-large.js (added)
-
JSTests/stress/typed-array-large-eventually-oob.js (added)
-
JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js (modified) (2 diffs)
-
JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js (modified) (1 diff)
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/storage/serialized-script-value.html (modified) (1 diff)
-
LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt (modified) (1 diff)
-
LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt (modified) (1 diff)
-
Source/JavaScriptCore/ChangeLog (modified) (2 diffs)
-
Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp (modified) (1 diff)
-
Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (modified) (9 diffs)
-
Source/JavaScriptCore/assembler/MacroAssembler.h (modified) (4 diffs)
-
Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (modified) (2 diffs)
-
Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h (modified) (1 diff)
-
Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (modified) (1 diff)
-
Source/JavaScriptCore/bytecode/AccessCase.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/bytecode/ArrayProfile.h (modified) (6 diffs)
-
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGArrayMode.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGArrayMode.h (modified) (10 diffs)
-
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (modified) (7 diffs)
-
Source/JavaScriptCore/dfg/DFGClobberize.h (modified) (5 diffs)
-
Source/JavaScriptCore/dfg/DFGCommon.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGDoesGC.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (modified) (9 diffs)
-
Source/JavaScriptCore/dfg/DFGGenerationInfo.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGHeapLocation.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGNode.h (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGNodeType.h (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.cpp (modified) (14 diffs)
-
Source/JavaScriptCore/dfg/DFGOperations.h (modified) (1 diff)
-
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGSafeToExecute.h (modified) (3 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (modified) (17 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (modified) (6 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (modified) (8 diffs)
-
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (modified) (2 diffs)
-
Source/JavaScriptCore/dfg/DFGValidate.cpp (modified) (1 diff)
-
Source/JavaScriptCore/ftl/FTLCapabilities.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (modified) (17 diffs)
-
Source/JavaScriptCore/ftl/FTLOutput.h (modified) (1 diff)
-
Source/JavaScriptCore/jit/IntrinsicEmitter.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/jit/JITOperations.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h (modified) (1 diff)
-
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/llint/LowLevelInterpreter.asm (modified) (3 diffs)
-
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (modified) (2 diffs)
-
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/ArrayBuffer.cpp (modified) (16 diffs)
-
Source/JavaScriptCore/runtime/ArrayBuffer.h (modified) (13 diffs)
-
Source/JavaScriptCore/runtime/ArrayBufferView.cpp (modified) (3 diffs)
-
Source/JavaScriptCore/runtime/ArrayBufferView.h (modified) (13 diffs)
-
Source/JavaScriptCore/runtime/AtomicsObject.cpp (modified) (1 diff)
-
Source/JavaScriptCore/runtime/DataView.cpp (modified) (4 diffs)
-
Source/JavaScriptCore/runtime/DataView.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/GenericTypedArrayView.h (modified) (10 diffs)
-
Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h (modified) (10 diffs)
-
Source/JavaScriptCore/runtime/JSArrayBufferView.cpp (modified) (9 diffs)
-
Source/JavaScriptCore/runtime/JSArrayBufferView.h (modified) (7 diffs)
-
Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSCJSValue.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSCJSValueInlines.h (modified) (1 diff)
-
Source/JavaScriptCore/runtime/JSDataView.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/JSDataView.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h (modified) (12 diffs)
-
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (modified) (13 diffs)
-
Source/JavaScriptCore/runtime/JSObject.h (modified) (6 diffs)
-
Source/JavaScriptCore/runtime/JSObjectInlines.h (modified) (2 diffs)
-
Source/JavaScriptCore/runtime/Operations.h (modified) (1 diff)
-
Source/JavaScriptCore/wasm/WasmPageCount.h (modified) (2 diffs)
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/wtf/CheckedArithmetic.h (modified) (12 diffs)
-
Source/WTF/wtf/PlatformUse.h (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/Modules/webaudio/AudioBuffer.cpp (modified) (2 diffs)
-
Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp (modified) (3 diffs)
-
Source/WebCore/bindings/js/SerializedScriptValue.cpp (modified) (24 diffs)
-
Source/WebCore/bindings/js/SerializedScriptValue.h (modified) (3 diffs)
-
Source/WebCore/fileapi/NetworkSendQueue.cpp (modified) (1 diff)
-
Source/WebCore/platform/graphics/PixelBuffer.cpp (modified) (1 diff)
-
Source/WebCore/platform/graphics/iso/ISOBox.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r284237 r284330 1 2021-10-16 Robin Morisset <rmorisset@apple.com> 2 3 Allow WASM to use up to 4GB 4 https://bugs.webkit.org/show_bug.cgi?id=229353 5 rdar://81603447 6 7 Reviewed by Yusuke Suzuki. 8 9 The big-wasm-memory/wasm-memory-requested... tests used to simply expect an OOM at 2GB. 10 They now expect success at 4GB, and failure at 4GB+1. 11 The exceptions they expect are now more specific, as previously there was a rounding issue that was causing the specific exceptions not to be thrown (resulting in the generic OOM exception later in the code). 12 Finally I made them only run on 64-bit platforms since we don't support typed arrays >=2GB on 32-bits, and I made them only run in one configuration since they can take a little bit of time. 13 14 I also added a few new tests, specifically checking our handling of large typed arrays, and especially of indices above INT32_MAX. 15 16 * stress/big-wasm-memory-grow-no-max.js: 17 (test): 18 * stress/big-wasm-memory-grow.js: 19 (test): 20 * stress/big-wasm-memory.js: 21 (test): 22 * stress/typed-array-always-large.js: Added. 23 (getArrayLength): 24 (getByVal): 25 (putByVal): 26 (test): 27 * stress/typed-array-eventually-large.js: Added. 28 (getArrayLength): 29 (getByVal): 30 (putByVal): 31 (test): 32 * stress/typed-array-large-eventually-oob.js: Added. 33 (getArrayLength): 34 (getByVal): 35 (putByVal): 36 (test): 37 * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js: 38 * wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js: 39 1 40 2021-10-15 Robin Morisset <rmorisset@apple.com> 2 41 -
trunk/JSTests/stress/big-wasm-memory-grow-no-max.js
r284237 r284330 1 //@ skip if $memoryLimited 1 //@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64") 2 //@ runDefault() 2 3 3 4 function test() { … … 25 26 foo(okArray); 26 27 28 let maxSize = 0x10000; 29 { 30 var memory = new WebAssembly.Memory({ initial: 0x1000 }); 31 memory.grow(maxSize - 0x1000); 32 var result = foo(new Uint8Array(memory.buffer)); 33 if (result !== void 0) 34 throw "Error: bad result at end: " + result; 35 } 36 27 37 var ok = false; 28 38 try { 29 39 var memory = new WebAssembly.Memory({ initial: 0x1000 }); 30 memory.grow( 0x7000);40 memory.grow(maxSize - 0x1000 + 1); 31 41 var result = foo(new Uint8Array(memory.buffer)); 32 if (result !== void 0)33 throw "Error: bad result at end: " + result;34 42 ok = true; 35 43 } catch (e) { 36 if (e.toString() != "RangeError: Out of memory")44 if (e.toString() != "RangeError: WebAssembly.Memory.grow expects the grown size to be a valid page count") 37 45 throw e; 38 46 } 39 40 47 if (ok) 41 48 throw "Error: did not throw error"; -
trunk/JSTests/stress/big-wasm-memory-grow.js
r284237 r284330 1 //@ skip if $memoryLimited 1 //@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64") 2 //@ runDefault() 2 3 3 4 function test() { … … 25 26 foo(okArray); 26 27 27 var ok = false; 28 try { 29 var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: 0x8000 }); 30 memory.grow(0x7000); 28 29 let maxSize = 0x10000; 30 { 31 var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize }); 32 memory.grow(maxSize - 0x1000); 31 33 var result = foo(new Uint8Array(memory.buffer)); 32 34 if (result !== void 0) 33 35 throw "Error: bad result at end: " + result; 36 } 37 38 var ok = false; 39 try { 40 var memory = new WebAssembly.Memory({ initial: 0x1000, maximum: maxSize+1 }); 41 memory.grow(maxSize + 1 - 0x1000); 42 var result = foo(new Uint8Array(memory.buffer)); 34 43 ok = true; 35 44 } catch (e) { 36 if (e.toString() != "RangeError: Out of memory")45 if (e.toString() != "RangeError: WebAssembly.Memory 'maximum' page count is too large") 37 46 throw e; 38 47 } 39 40 48 if (ok) 41 49 throw "Error: did not throw error"; -
trunk/JSTests/stress/big-wasm-memory.js
r284237 r284330 1 //@ skip if $memoryLimited 1 //@ skip if $memoryLimited or ($architecture != "arm64" && $architecture != "x86-64") 2 //@ runDefault() 2 3 3 4 function test() { … … 25 26 foo(okArray); 26 27 28 let maxSize = 0x10000; 29 { 30 var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize, maximum: maxSize }).buffer)); 31 if (result !== void 0) 32 throw "Error: bad result at end: " + result; 33 } 34 27 35 var ok = false; 28 36 try { 29 var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: 0x8000, maximum: 0x8000 }).buffer)); 30 if (result !== void 0) 31 throw "Error: bad result at end: " + result; 37 var result = foo(new Uint8Array(new WebAssembly.Memory({ initial: maxSize+1, maximum: maxSize+1 }).buffer)); 32 38 ok = true; 33 39 } catch (e) { 34 if (e.toString() != "RangeError: Out of memory")40 if (e.toString() != "RangeError: WebAssembly.Memory 'initial' page count is too large") 35 41 throw e; 36 42 } 37 38 43 if (ok) 39 44 throw "Error: did not throw error"; -
trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE-2.js
r284237 r284330 77 77 try { 78 78 var module = new WasmModuleBuilder(); 79 module.addMemory( 32768);79 module.addMemory((2**16) + 1); 80 80 module.instantiate(); 81 81 } catch (e) { … … 83 83 } 84 84 85 if (exception != " RangeError: Out of memory") {85 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())')") { 86 86 print(exception); 87 87 throw "FAILED"; -
trunk/JSTests/wasm/regress/wasm-memory-requested-more-than-MAX_ARRAY_BUFFER_SIZE.js
r284237 r284330 2 2 3 3 try { 4 new WebAssembly.Memory({ initial: 0x 8000, maximum: 0x8000}).buffer;4 new WebAssembly.Memory({ initial: 0x10001, maximum: 0x10001 }).buffer; 5 5 } catch (e) { 6 6 exception = e; 7 7 } 8 8 9 if (exception != "RangeError: Out of memory")10 throw "FAILED ";9 if (exception != "RangeError: WebAssembly.Memory 'initial' page count is too large") 10 throw "FAILED, exception was: " + exception; -
trunk/LayoutTests/ChangeLog
r284328 r284330 1 2021-10-16 Robin Morisset <rmorisset@apple.com> 2 3 Allow WASM to use up to 4GB 4 https://bugs.webkit.org/show_bug.cgi?id=229353 5 rdar://81603447 6 7 Reviewed by Yusuke Suzuki. 8 9 Rebaselined three following tests as different or fewer error messages appear on the console. 10 Also changed currentVersion in serialized-script-value.html from 9 to 10. 11 12 * fast/canvas/canvas-getImageData-invalid-result-buffer-crash-expected.txt: 13 * fast/storage/serialized-script-value.html: 14 * webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt: 15 * webaudio/OfflineAudioContext/bad-buffer-length-expected.txt: 16 1 17 2021-10-16 Tim Horton <timothy_horton@apple.com> 2 18 -
trunk/LayoutTests/fast/storage/serialized-script-value.html
r284237 r284330 7 7 <script> 8 8 9 const currentVersion = 0x0 9;9 const currentVersion = 0x0a; 10 10 11 11 // Here's a little Q&D helper for future adventurers needing to rebaseline this. -
trunk/LayoutTests/webaudio/OfflineAudioContext-bad-buffer-crash-expected.txt
r284237 r284330 1 CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.2 1 This test passes if it does not crash. 3 2 -
trunk/LayoutTests/webaudio/OfflineAudioContext/bad-buffer-length-expected.txt
r284237 r284330 1 CONSOLE MESSAGE: Failed to construct internal AudioBuffer with 1 channel(s), a sample rate of 44000 and a length of 536870912.2 1 Make sure that the length returned by OfflineAudioContext even if we failed to construct the rendering buffer. 3 2 -
trunk/Source/JavaScriptCore/ChangeLog
r284298 r284330 1 2021-10-16 Robin Morisset <rmorisset@apple.com> 2 3 Allow WASM to use up to 4GB 4 https://bugs.webkit.org/show_bug.cgi?id=229353 5 rdar://81603447 6 7 Reviewed by Yusuke Suzuki. 8 9 While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work: 10 - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being size_t. 11 - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size. 12 In order to avoid performance regressions, I had to add speculation in the DFG/FTL, which now have two versions of NewTypedArray (one that takes an Int32 and one that takes a StrictInt52) 13 - Similarly, GetArrayLength and GetTypedArrayByteOffset now can either return an Int32 or a larger number. 14 I also had to split them in the DFG/FTL, see GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 for examples 15 - In turns, I had to add CheckInBoundsInt52 since CheckInBounds could not accept the result of GetTypedArrayLengthAsInt52 16 - I modified the runtime functions for GetByVal/PutByVal/DataViewGet/DataViewSet/AtomicsXXX to accept non-Int32 indices, since for {Int8/UInt8/UInt8Clamped}Array, a maximum size of 4GB implies indices > 2B. 17 - I added a "mayBeLargeTypedArray" bit to ArrayProfile/UnlinkedArrayProfile/DFG::ArrayMode to track whether such a non-Int32 index was seen to allow proper speculation and specialization of fast paths in the DFG/FTL. 18 I then updated the runtime functions used by the slow paths to correctly update it. 19 20 Unfortunately I ran out of time to add all the speculations/update all the fast paths. 21 So the following will have to wait for a follow-up patch: 22 - Accepting large indices in the fast path of GetByVal in the LLInt 23 - Accepting large indices in the fast paths generated by AccessCase/PolymorphicAccess 24 - Accepting large indices in the fast paths generated by the DFG/FTL for each of GetByVal/PutByVal/DataViewGet/DataViewSet/AtomicsXXX 25 26 The current patch is functional, it will just have dreadful performance if trying to use indices >2B in a {Int8/UInt8/UInt8Clamped}Array. 27 28 Other minor changes in this patch: 29 - Fixed an undefined behavior in ArrayBuffer::createInternal where memcpy could be called on nullptr (the spec explicitly bans this even when length is 0) 30 - Replaced some repetitive and error-prone bounds checking by calls to WTF::isSumSmallerThanOrEqual, which is clearer, shorter, and reuse CheckedArithmetic facilities to avoid overflow issues. 31 - Fixed a variety of obsolete comments 32 - Added support for branch64(RelationalCondition cond, RegisterID left, Imm64 right) 33 (there was already support for the same but with TrustedImm64) 34 - Made various AbstractMacroAssembler function constexpr as part of the previous point 35 36 * assembler/AbstractMacroAssembler.cpp: 37 * assembler/AbstractMacroAssembler.h: 38 (JSC::AbstractMacroAssembler::TrustedImmPtr::TrustedImmPtr): 39 (JSC::AbstractMacroAssembler::TrustedImmPtr::asIntptr): 40 (JSC::AbstractMacroAssembler::TrustedImmPtr::asPtr): 41 (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr): 42 (JSC::AbstractMacroAssembler::ImmPtr::asTrustedImmPtr): 43 (JSC::AbstractMacroAssembler::TrustedImm32::TrustedImm32): 44 (JSC::AbstractMacroAssembler::Imm32::Imm32): 45 (JSC::AbstractMacroAssembler::Imm32::asTrustedImm32 const): 46 (JSC::AbstractMacroAssembler::TrustedImm64::TrustedImm64): 47 (JSC::AbstractMacroAssembler::Imm64::Imm64): 48 (JSC::AbstractMacroAssembler::Imm64::asTrustedImm64 const): 49 (JSC::AbstractMacroAssembler::canBlind): 50 (JSC::AbstractMacroAssembler::shouldBlindForSpecificArch): 51 * assembler/MacroAssembler.h: 52 (JSC::MacroAssembler::branch64): 53 * assembler/MacroAssemblerARM64.h: 54 (JSC::MacroAssemblerARM64::shouldBlindForSpecificArch): 55 (JSC::MacroAssemblerARM64::branch64): 56 * assembler/MacroAssemblerARM64E.h: 57 (JSC::MacroAssemblerARM64E::untagArrayPtrLength64): 58 (JSC::MacroAssemblerARM64E::untagArrayPtrLength32): Deleted. 59 * assembler/MacroAssemblerX86Common.h: 60 (JSC::MacroAssemblerX86Common::canBlind): 61 (JSC::MacroAssemblerX86Common::shouldBlindForSpecificArch): 62 * bytecode/AccessCase.cpp: 63 (JSC::AccessCase::needsScratchFPR const): 64 (JSC::AccessCase::generateWithGuard): 65 * bytecode/ArrayProfile.h: 66 (JSC::ArrayProfile::setMayBeLargeTypedArray): 67 (JSC::ArrayProfile::mayBeLargeTypedArray const): 68 (JSC::UnlinkedArrayProfile::UnlinkedArrayProfile): 69 (JSC::UnlinkedArrayProfile::update): 70 * dfg/DFGAbstractInterpreterInlines.h: 71 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 72 * dfg/DFGArgumentsEliminationPhase.cpp: 73 * dfg/DFGArrayMode.cpp: 74 (JSC::DFG::ArrayMode::refine const): 75 * dfg/DFGArrayMode.h: 76 (JSC::DFG::ArrayMode::ArrayMode): 77 (JSC::DFG::ArrayMode::mayBeLargeTypedArray const): 78 (JSC::DFG::ArrayMode::withType const): 79 (JSC::DFG::ArrayMode::withSpeculation const): 80 (JSC::DFG::ArrayMode::withConversion const): 81 (JSC::DFG::ArrayMode::withTypeAndConversion const): 82 (JSC::DFG::ArrayMode::withArrayClassAndSpeculationAndMayBeLargeTypedArray const): 83 (JSC::DFG::ArrayMode::speculationFromProfile): 84 (JSC::DFG::ArrayMode::withSpeculationFromProfile const): 85 (JSC::DFG::ArrayMode::withProfile const): 86 (JSC::DFG::ArrayMode::operator== const): 87 (JSC::DFG::ArrayMode::withArrayClass const): Deleted. 88 * dfg/DFGByteCodeParser.cpp: 89 (JSC::DFG::ByteCodeParser::handleIntrinsicGetter): 90 * dfg/DFGClobberize.h: 91 (JSC::DFG::clobberize): 92 * dfg/DFGCommon.h: 93 (JSC::DFG::enableInt52): 94 * dfg/DFGConstantFoldingPhase.cpp: 95 (JSC::DFG::ConstantFoldingPhase::foldConstants): 96 * dfg/DFGDoesGC.cpp: 97 (JSC::DFG::doesGC): 98 * dfg/DFGFixupPhase.cpp: 99 (JSC::DFG::FixupPhase::fixupNode): 100 (JSC::DFG::FixupPhase::convertToGetArrayLength): 101 (JSC::DFG::FixupPhase::prependGetArrayLength): Deleted. 102 * dfg/DFGGenerationInfo.h: 103 * dfg/DFGHeapLocation.cpp: 104 (WTF::printInternal): 105 * dfg/DFGHeapLocation.h: 106 * dfg/DFGIntegerRangeOptimizationPhase.cpp: 107 * dfg/DFGNode.h: 108 (JSC::DFG::Node::hasStorageChild const): 109 (JSC::DFG::Node::storageChildIndex): 110 (JSC::DFG::Node::hasArrayMode): 111 * dfg/DFGNodeType.h: 112 * dfg/DFGOperations.cpp: 113 (JSC::DFG::putByVal): 114 (JSC::DFG::newTypedArrayWithSize): 115 (JSC::DFG::JSC_DEFINE_JIT_OPERATION): 116 * dfg/DFGOperations.h: 117 * dfg/DFGPredictionPropagationPhase.cpp: 118 * dfg/DFGSSALoweringPhase.cpp: 119 (JSC::DFG::SSALoweringPhase::handleNode): 120 (JSC::DFG::SSALoweringPhase::lowerBoundsCheck): 121 * dfg/DFGSafeToExecute.h: 122 (JSC::DFG::safeToExecute): 123 * dfg/DFGSpeculativeJIT.cpp: 124 (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds): 125 (JSC::DFG::SpeculativeJIT::emitTypedArrayBoundsCheck): 126 (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): 127 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 128 (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): 129 (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): 130 (JSC::DFG::SpeculativeJIT::cageTypedArrayStorage): 131 (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset): 132 (JSC::DFG::SpeculativeJIT::compileGetArrayLength): 133 (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithSize): 134 (JSC::DFG::SpeculativeJIT::emitNewTypedArrayWithSizeInRegister): 135 (JSC::DFG::SpeculativeJIT::compileNewTypedArray): 136 * dfg/DFGSpeculativeJIT.h: 137 * dfg/DFGSpeculativeJIT32_64.cpp: 138 (JSC::DFG::SpeculativeJIT::compileGetByVal): 139 (JSC::DFG::SpeculativeJIT::compile): 140 * dfg/DFGSpeculativeJIT64.cpp: 141 (JSC::DFG::SpeculativeJIT::compileNewTypedArrayWithInt52Size): 142 (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLengthAsInt52): 143 (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52): 144 (JSC::DFG::SpeculativeJIT::compile): 145 * dfg/DFGTypeCheckHoistingPhase.cpp: 146 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks): 147 (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks): 148 * dfg/DFGValidate.cpp: 149 * ftl/FTLCapabilities.cpp: 150 (JSC::FTL::canCompile): 151 * ftl/FTLLowerDFGToB3.cpp: 152 (JSC::FTL::DFG::LowerDFGToB3::validateAIState): 153 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 154 (JSC::FTL::DFG::LowerDFGToB3::emitGetTypedArrayByteOffsetExceptSettingResult): 155 (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffset): 156 (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayByteOffsetAsInt52): 157 (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength): 158 (JSC::FTL::DFG::LowerDFGToB3::compileGetTypedArrayLengthAsInt52): 159 (JSC::FTL::DFG::LowerDFGToB3::compileCheckInBoundsInt52): 160 (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal): 161 (JSC::FTL::DFG::LowerDFGToB3::compileNewTypedArray): 162 (JSC::FTL::DFG::LowerDFGToB3::emitNewTypedArrayWithSize): 163 (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq): 164 * ftl/FTLOutput.h: 165 (JSC::FTL::Output::load64NonNegative): 166 * jit/IntrinsicEmitter.cpp: 167 (JSC::IntrinsicGetterAccessCase::emitIntrinsicGetter): 168 * jit/JITOperations.cpp: 169 (JSC::putByVal): 170 (JSC::getByVal): 171 * llint/LLIntOfflineAsmConfig.h: 172 * llint/LLIntSlowPaths.cpp: 173 (JSC::LLInt::getByVal): 174 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 175 * llint/LowLevelInterpreter.asm: 176 * llint/LowLevelInterpreter32_64.asm: 177 * llint/LowLevelInterpreter64.asm: 178 * runtime/ArrayBuffer.cpp: 179 (JSC::SharedArrayBufferContents::SharedArrayBufferContents): 180 (JSC::ArrayBufferContents::ArrayBufferContents): 181 (JSC::ArrayBufferContents::tryAllocate): 182 (JSC::ArrayBuffer::create): 183 (JSC::ArrayBuffer::createAdopted): 184 (JSC::ArrayBuffer::createFromBytes): 185 (JSC::ArrayBuffer::tryCreate): 186 (JSC::ArrayBuffer::createUninitialized): 187 (JSC::ArrayBuffer::tryCreateUninitialized): 188 (JSC::ArrayBuffer::createInternal): 189 (JSC::ArrayBuffer::clampValue): 190 (JSC::ArrayBuffer::clampIndex const): 191 (JSC::ArrayBuffer::sliceWithClampedIndex const): 192 * runtime/ArrayBuffer.h: 193 (JSC::ArrayBufferContents::sizeInBytes const): 194 (JSC::ArrayBuffer::byteLength const): 195 (JSC::ArrayBuffer::gcSizeEstimateInBytes const): 196 * runtime/ArrayBufferView.cpp: 197 (JSC::ArrayBufferView::ArrayBufferView): 198 * runtime/ArrayBufferView.h: 199 (JSC::ArrayBufferView::byteOffset const): 200 (JSC::ArrayBufferView::byteLength const): 201 (JSC::ArrayBufferView::verifyByteOffsetAlignment): 202 (JSC::ArrayBufferView::verifySubRangeLength): 203 (JSC::ArrayBufferView::clampOffsetAndNumElements): 204 (JSC::ArrayBufferView::setImpl): 205 (JSC::ArrayBufferView::setRangeImpl): 206 (JSC::ArrayBufferView::getRangeImpl): 207 (JSC::ArrayBufferView::zeroRangeImpl): 208 (JSC::ArrayBufferView::calculateOffsetAndLength): Deleted. 209 * runtime/AtomicsObject.cpp: 210 * runtime/DataView.cpp: 211 (JSC::DataView::DataView): 212 (JSC::DataView::create): 213 * runtime/DataView.h: 214 * runtime/GenericTypedArrayView.h: 215 * runtime/GenericTypedArrayViewInlines.h: 216 (JSC::GenericTypedArrayView<Adaptor>::GenericTypedArrayView): 217 (JSC::GenericTypedArrayView<Adaptor>::create): 218 (JSC::GenericTypedArrayView<Adaptor>::tryCreate): 219 (JSC::GenericTypedArrayView<Adaptor>::createUninitialized): 220 (JSC::GenericTypedArrayView<Adaptor>::tryCreateUninitialized): 221 (JSC::GenericTypedArrayView<Adaptor>::subarray const): Deleted. 222 * runtime/JSArrayBufferView.cpp: 223 (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext): 224 (JSC::JSArrayBufferView::byteLength const): 225 (JSC::JSArrayBufferView::slowDownAndWasteMemory): 226 (JSC::JSArrayBufferView::possiblySharedImpl): 227 * runtime/JSArrayBufferView.h: 228 (JSC::JSArrayBufferView::sizeOf): 229 (JSC::JSArrayBufferView::ConstructionContext::length const): 230 (JSC::JSArrayBufferView::length const): 231 * runtime/JSArrayBufferViewInlines.h: 232 (JSC::JSArrayBufferView::byteOffsetImpl): 233 (JSC::JSArrayBufferView::byteOffset): 234 (JSC::JSArrayBufferView::byteOffsetConcurrently): 235 * runtime/JSCJSValue.h: 236 * runtime/JSCJSValueInlines.h: 237 (JSC::JSValue::toIndex const): 238 (JSC::JSValue::toTypedArrayIndex const): 239 * runtime/JSDataView.cpp: 240 (JSC::JSDataView::create): 241 (JSC::JSDataView::createUninitialized): 242 (JSC::JSDataView::set): 243 (JSC::JSDataView::setIndex): 244 * runtime/JSDataView.h: 245 * runtime/JSDataViewPrototype.cpp: 246 (JSC::getData): 247 (JSC::setData): 248 * runtime/JSGenericTypedArrayView.h: 249 * runtime/JSGenericTypedArrayViewConstructorInlines.h: 250 (JSC::constructGenericTypedArrayViewWithArguments): 251 (JSC::constructGenericTypedArrayViewImpl): 252 * runtime/JSGenericTypedArrayViewInlines.h: 253 (JSC::JSGenericTypedArrayView<Adaptor>::create): 254 (JSC::JSGenericTypedArrayView<Adaptor>::createWithFastVector): 255 (JSC::JSGenericTypedArrayView<Adaptor>::createUninitialized): 256 (JSC::JSGenericTypedArrayView<Adaptor>::validateRange): 257 (JSC::JSGenericTypedArrayView<Adaptor>::setWithSpecificType): 258 (JSC::JSGenericTypedArrayView<Adaptor>::set): 259 * runtime/JSObject.h: 260 (JSC::JSObject::putByIndexInline): 261 (JSC::JSObject::tryGetIndexQuickly const): 262 (JSC::JSObject::trySetIndexQuickly): 263 (JSC::JSObject::canSetIndexQuickly): Deleted. 264 * runtime/JSObjectInlines.h: 265 (JSC::JSObject::getIndexQuicklyForTypedArray const): 266 (JSC::JSObject::setIndexQuicklyForArrayStorageIndexingType): 267 (JSC::JSObject::trySetIndexQuicklyForTypedArray): 268 (JSC::JSObject::canSetIndexQuicklyForTypedArray const): Deleted. 269 * runtime/Operations.h: 270 (JSC::getByValWithIndex): 271 * wasm/WasmPageCount.h: 272 1 273 2021-10-15 Ross Kirsling <ross.kirsling@sony.com> 2 274 … … 362 634 363 635 While increasing MAX_ARRAY_BUFFER_SIZE to 4GB was easy, it was not remotely the only thing required to get this to work: 364 - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being UCPURegister.636 - 4GB is not representable in a uint32_t, so I changed all length of ArrayBuffer/TypedArray/etc.. to being size_t. 365 637 - This also required changing NewTypedArray in all of LLInt/Baseline/DFG/FTL to accept a non-int32 size. 366 638 In order to avoid performance regressions, I had to add speculation in the DFG/FTL, which now have two versions of NewTypedArray (one that takes an Int32 and one that takes a StrictInt52) -
trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without -
trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
r284237 r284330 266 266 // from pointers used as absolute addresses to memory operations 267 267 struct TrustedImmPtr : public TrustedImm { 268 TrustedImmPtr() { }269 270 explicit TrustedImmPtr(const void* value)268 constexpr TrustedImmPtr() { } 269 270 explicit constexpr TrustedImmPtr(const void* value) 271 271 : m_value(value) 272 272 { … … 279 279 } 280 280 281 explicit TrustedImmPtr(std::nullptr_t)282 { 283 } 284 285 explicit TrustedImmPtr(size_t value)281 explicit constexpr TrustedImmPtr(std::nullptr_t) 282 { 283 } 284 285 explicit constexpr TrustedImmPtr(size_t value) 286 286 : m_value(reinterpret_cast<void*>(value)) 287 287 { 288 288 } 289 289 290 intptr_t asIntptr()290 constexpr intptr_t asIntptr() 291 291 { 292 292 return reinterpret_cast<intptr_t>(m_value); 293 293 } 294 294 295 void* asPtr()295 constexpr void* asPtr() 296 296 { 297 297 return const_cast<void*>(m_value); … … 303 303 struct ImmPtr : private TrustedImmPtr 304 304 { 305 explicit ImmPtr(const void* value)305 explicit constexpr ImmPtr(const void* value) 306 306 : TrustedImmPtr(value) 307 307 { 308 308 } 309 309 310 TrustedImmPtr asTrustedImmPtr() { return *this; }310 constexpr TrustedImmPtr asTrustedImmPtr() { return *this; } 311 311 }; 312 312 … … 326 326 327 327 #if !CPU(X86_64) 328 explicit TrustedImm32(TrustedImmPtr ptr)328 explicit constexpr TrustedImm32(TrustedImmPtr ptr) 329 329 : m_value(ptr.asIntptr()) 330 330 { … … 337 337 338 338 struct Imm32 : private TrustedImm32 { 339 explicit Imm32(int32_t value)339 explicit constexpr Imm32(int32_t value) 340 340 : TrustedImm32(value) 341 341 { 342 342 } 343 343 #if !CPU(X86_64) 344 explicit Imm32(TrustedImmPtr ptr)344 explicit constexpr Imm32(TrustedImmPtr ptr) 345 345 : TrustedImm32(ptr) 346 346 { 347 347 } 348 348 #endif 349 const TrustedImm32& asTrustedImm32() const { return *this; }349 constexpr const TrustedImm32& asTrustedImm32() const { return *this; } 350 350 351 351 }; … … 358 358 // immediate values. 359 359 struct TrustedImm64 : TrustedImm { 360 TrustedImm64() { }361 362 explicit TrustedImm64(int64_t value)360 constexpr TrustedImm64() { } 361 362 explicit constexpr TrustedImm64(int64_t value) 363 363 : m_value(value) 364 364 { … … 366 366 367 367 #if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64) 368 explicit TrustedImm64(TrustedImmPtr ptr)368 explicit constexpr TrustedImm64(TrustedImmPtr ptr) 369 369 : m_value(ptr.asIntptr()) 370 370 { … … 377 377 struct Imm64 : private TrustedImm64 378 378 { 379 explicit Imm64(int64_t value)379 explicit constexpr Imm64(int64_t value) 380 380 : TrustedImm64(value) 381 381 { 382 382 } 383 383 #if CPU(X86_64) || CPU(ARM64) || CPU(RISCV64) 384 explicit Imm64(TrustedImmPtr ptr)384 explicit constexpr Imm64(TrustedImmPtr ptr) 385 385 : TrustedImm64(ptr) 386 386 { 387 387 } 388 388 #endif 389 const TrustedImm64& asTrustedImm64() const { return *this; }389 constexpr const TrustedImm64& asTrustedImm64() const { return *this; } 390 390 }; 391 391 … … 1054 1054 return firstRegister(); 1055 1055 } 1056 static bool canBlind() { return false; }1057 static bool shouldBlindForSpecificArch(uint32_t) { return false; }1058 static bool shouldBlindForSpecificArch(uint64_t) { return false; }1056 static constexpr bool canBlind() { return false; } 1057 static constexpr bool shouldBlindForSpecificArch(uint32_t) { return false; } 1058 static constexpr bool shouldBlindForSpecificArch(uint64_t) { return false; } 1059 1059 1060 1060 class CachedTempRegister { -
trunk/Source/JavaScriptCore/assembler/MacroAssembler.h
r284237 r284330 140 140 #if CPU(ARM64) || CPU(ARM_THUMB2) || CPU(X86_64) || CPU(MIPS) || CPU(RISCV64) 141 141 using MacroAssemblerBase::branchPtr; 142 #endif 143 #if CPU(X86_64) 144 using MacroAssemblerBase::branch64; 142 145 #endif 143 146 using MacroAssemblerBase::branchSub32; … … 1461 1464 and64(imm.asTrustedImm32(), dest); 1462 1465 } 1466 1463 1467 #endif // USE(JSVALUE64) 1464 1468 … … 1728 1732 } 1729 1733 1730 #endif // CPU(X86_64) || CPU(ARM64) 1734 #endif // CPU(X86_64) || CPU(ARM64) || CPU(RISCV64) 1731 1735 1732 1736 void store32(Imm32 imm, Address dest) … … 1821 1825 return branch32(cond, left, right.asTrustedImm32()); 1822 1826 } 1827 1828 #if CPU(X86_64) 1829 // Other 64-bit platforms don't need blinding, and have branch64(RelationalCondition, RegisterID, Imm64) directly defined in the right file. 1830 // We cannot put this in MacroAssemblerX86_64.h, because it uses shouldBlind(), loadRoationBlindedConstant, etc.. which are only defined here and not there. 1831 Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right) 1832 { 1833 if (shouldBlind(right)) { 1834 if (haveScratchRegisterForBlinding()) { 1835 loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegisterForBlinding()); 1836 return branch64(cond, left, scratchRegisterForBlinding()); 1837 } 1838 1839 // If we don't have a scratch register available for use, we'll just 1840 // place a random number of nops. 1841 uint32_t nopCount = random() & 3; 1842 while (nopCount--) 1843 nop(); 1844 return branch64(cond, left, right.asTrustedImm64()); 1845 } 1846 return branch64(cond, left, right.asTrustedImm64()); 1847 } 1848 #endif // CPU(X86_64) 1823 1849 1824 1850 void compare32(RelationalCondition cond, RegisterID left, Imm32 right, RegisterID dest) -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
r284237 r284330 145 145 146 146 // FIXME: Get reasonable implementations for these 147 static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }148 static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }147 static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; } 148 static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; } 149 149 150 150 // Integer operations: … … 3304 3304 } 3305 3305 return Jump(makeBranch(cond)); 3306 } 3307 3308 Jump branch64(RelationalCondition cond, RegisterID left, Imm64 right) 3309 { 3310 return branch64(cond, left, right.asTrustedImm64()); 3306 3311 } 3307 3312 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
r284237 r284330 133 133 } 134 134 135 ALWAYS_INLINE void untagArrayPtrLength 32(Address length, RegisterID target, bool validateAuth)135 ALWAYS_INLINE void untagArrayPtrLength64(Address length, RegisterID target, bool validateAuth) 136 136 { 137 137 auto lengthGPR = getCachedDataTempRegisterIDAndInvalidate(); 138 load 32(length, lengthGPR);138 load64(length, lengthGPR); 139 139 auto scratch = validateAuth ? getCachedMemoryTempRegisterIDAndInvalidate() : InvalidGPRReg; 140 140 untagArrayPtr(lengthGPR, target, validateAuth, scratch); -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r284237 r284330 109 109 static constexpr RegisterID framePointerRegister = X86Registers::ebp; 110 110 111 static bool c anBlind() { return true; }112 static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }113 static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }111 static bool constexpr canBlind() { return true; } 112 static bool constexpr shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; } 113 static bool constexpr shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; } 114 114 115 115 // Integer arithmetic operations: -
trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp
r284237 r284330 487 487 case CustomValueSetter: 488 488 case CustomAccessorSetter: 489 case IntrinsicGetter:490 489 case InHit: 491 490 case InMiss: … … 530 529 case IndexedTypedArrayFloat32Store: 531 530 case IndexedTypedArrayFloat64Store: 531 // Used by TypedArrayLength/TypedArrayByteOffset in the process of boxing their result as a double 532 case IntrinsicGetter: 532 533 return true; 533 534 } … … 1185 1186 GPRReg propertyGPR = state.u.propertyGPR; 1186 1187 1187 1188 1188 jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR); 1189 1189 fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type)))); 1190 1190 1191 jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR); 1192 state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR)); 1191 CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()); 1192 jit.signExtend32ToPtr(propertyGPR, scratchGPR); 1193 #if USE(LARGE_TYPED_ARRAYS) 1194 // The length is a size_t, so either 32 or 64 bits depending on the platform. 1195 state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength)); 1196 #else 1197 state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength)); 1198 #endif 1193 1199 1194 1200 auto allocator = state.makeDefaultScratchAllocator(scratchGPR); … … 1198 1204 jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); 1199 1205 1206 #if USE(LARGE_TYPED_ARRAYS) 1207 jit.load64(addressOfLength, scratchGPR); 1208 #else 1209 jit.load32(addressOfLength, scratchGPR); 1210 #endif 1200 1211 jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR); 1201 1212 jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false); 1202 1203 1213 jit.signExtend32ToPtr(propertyGPR, scratchGPR); 1204 1214 if (isInt(type)) { … … 1596 1606 } 1597 1607 1598 jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR); 1599 // OutOfBounds bit of ArrayProfile will be set in the operation function. 1600 state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR)); 1608 CCallHelpers::Address addressOfLength = CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()); 1609 jit.signExtend32ToPtr(propertyGPR, scratchGPR); 1610 #if USE(LARGE_TYPED_ARRAYS) 1611 // The length is a UCPURegister, so either 32 or 64 bits depending on the platform. 1612 state.failAndRepatch.append(jit.branch64(CCallHelpers::AboveOrEqual, scratchGPR, addressOfLength)); 1613 #else 1614 state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, addressOfLength)); 1615 #endif 1601 1616 1602 1617 auto allocator = state.makeDefaultScratchAllocator(scratchGPR); … … 1606 1621 jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace); 1607 1622 1623 #if USE(LARGE_TYPED_ARRAYS) 1624 jit.load64(addressOfLength, scratchGPR); 1625 #else 1626 jit.load32(addressOfLength, scratchGPR); 1627 #endif 1608 1628 jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR); 1609 1629 jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false); 1610 1611 1630 jit.signExtend32ToPtr(propertyGPR, scratchGPR); 1612 1631 if (isInt(type)) { -
trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h
r284237 r284330 37 37 // This is a bitfield where each bit represents an type of array access that we have seen. 38 38 // There are 19 indexing types that use the lower bits. 39 // There are 9 typed array types taking the bits 16 to 25.39 // There are 11 typed array types taking the bits 16-20 and 26-31. 40 40 typedef unsigned ArrayModes; 41 41 … … 206 206 { 207 207 } 208 208 209 #if USE(LARGE_TYPED_ARRAYS) 210 static constexpr uint64_t s_smallTypedArrayMaxLength = std::numeric_limits<int32_t>::max(); 211 void setMayBeLargeTypedArray() { m_mayBeLargeTypedArray = true; } 212 bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return m_mayBeLargeTypedArray; } 213 #else 214 bool mayBeLargeTypedArray(const ConcurrentJSLocker&) const { return false; } 215 #endif 216 209 217 StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; } 210 218 ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; } … … 245 253 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. 246 254 bool m_outOfBounds { false }; 255 #if USE(LARGE_TYPED_ARRAYS) 256 bool m_mayBeLargeTypedArray { false }; 257 #endif 247 258 bool m_mayInterceptIndexedAccesses : 1; 248 259 bool m_usesOriginalArrayStructures : 1; … … 254 265 class UnlinkedArrayProfile { 255 266 public: 256 UnlinkedArrayProfile() = default; 267 explicit UnlinkedArrayProfile() 268 : m_usesOriginalArrayStructures(true) 269 #if USE(LARGE_TYPED_ARRAYS) 270 , m_mayBeLargeTypedArray(false) 271 #endif 272 { 273 } 257 274 258 275 void update(ArrayProfile& arrayProfile) … … 281 298 else 282 299 m_usesOriginalArrayStructures = arrayProfile.m_usesOriginalArrayStructures; 300 301 #if USE(LARGE_TYPED_ARRAYS) 302 if (m_mayBeLargeTypedArray) 303 arrayProfile.m_mayBeLargeTypedArray = true; 304 else 305 m_mayBeLargeTypedArray = arrayProfile.m_mayBeLargeTypedArray; 306 #endif 283 307 } 284 308 … … 291 315 bool m_outOfBounds { false }; 292 316 bool m_mayInterceptIndexedAccesses { false }; 293 bool m_usesOriginalArrayStructures { true }; 317 bool m_usesOriginalArrayStructures : 1; 318 #if USE(LARGE_TYPED_ARRAYS) 319 bool m_mayBeLargeTypedArray : 1; 320 #endif 294 321 }; 322 static_assert(sizeof(UnlinkedArrayProfile) <= 8); 295 323 296 324 } // namespace JSC -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r284237 r284330 3464 3464 JSArrayBufferView* view = m_graph.tryGetFoldableView( 3465 3465 forNode(node->child1()).m_value, node->arrayMode()); 3466 if (view && isInBounds<int32_t>(view->length())) { 3467 setConstant(node, jsNumber(view->length())); 3468 break; 3469 } 3470 setNonCellTypeForNode(node, SpecInt32Only); 3471 break; 3472 } 3473 3474 case GetTypedArrayLengthAsInt52: { 3475 JSArrayBufferView* view = m_graph.tryGetFoldableView( 3476 forNode(node->child1()).m_value, node->arrayMode()); 3466 3477 if (view) { 3467 3478 setConstant(node, jsNumber(view->length())); 3468 3479 break; 3469 3480 } 3470 setNonCellTypeForNode(node, SpecInt 32Only);3481 setNonCellTypeForNode(node, SpecInt52Any); 3471 3482 break; 3472 3483 } … … 3797 3808 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value); 3798 3809 if (view) { 3799 std::optional<unsigned> byteOffset = view->byteOffsetConcurrently(); 3810 std::optional<size_t> byteOffset = view->byteOffsetConcurrently(); 3811 if (byteOffset && isInBounds<int32_t>(byteOffset)) { 3812 setConstant(node, jsNumber(*byteOffset)); 3813 break; 3814 } 3815 } 3816 setNonCellTypeForNode(node, SpecInt32Only); 3817 break; 3818 } 3819 3820 case GetTypedArrayByteOffsetAsInt52: { 3821 JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value); 3822 if (view) { 3823 std::optional<size_t> byteOffset = view->byteOffsetConcurrently(); 3800 3824 if (byteOffset) { 3801 3825 setConstant(node, jsNumber(*byteOffset)); … … 3803 3827 } 3804 3828 } 3805 setNonCellTypeForNode(node, SpecInt 32Only);3829 setNonCellTypeForNode(node, SpecInt52Any); 3806 3830 break; 3807 3831 } … … 4107 4131 // thing to do here. We pick NodeResultJS because it makes converting this to an identity 4108 4132 // easier. 4133 setNonCellTypeForNode(node, SpecInt32Only); 4134 break; 4135 } 4136 case CheckInBoundsInt52: { 4137 // See the CheckInBounds case, it does not really matter what we put here. 4109 4138 setNonCellTypeForNode(node, SpecInt32Only); 4110 4139 break; -
trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
r284237 r284330 324 324 if ((node->child1()->op() == NewArrayWithSpread) && !node->origin.exitOK) 325 325 escape(node->child1(), node); 326 break; 327 328 case GetTypedArrayLengthAsInt52: 329 // This node is only used for TypedArrays, so should not be relevant for arguments elimination 330 escape(node->child2(), node); 326 331 break; 327 332 -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r284237 r284330 210 210 } 211 211 212 if (!isInt32Speculation(index) )212 if (!isInt32Speculation(index) && !mayBeLargeTypedArray()) 213 213 return ArrayMode(Array::Generic, action()); 214 214 … … 295 295 case Array::BigInt64Array: 296 296 case Array::BigUint64Array: 297 // FIXME: no idea why we only preserve this out-of-bounds information for PutByVal and not GetByVal as well. 298 // https://bugs.webkit.org/show_bug.cgi?id=231276 297 299 if (node->op() == PutByVal) { 298 300 if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds()) -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h
r284237 r284330 128 128 u.asBytes.conversion = Array::AsIs; 129 129 u.asBytes.action = Array::Write; 130 u.asBytes.mayBeLargeTypedArray = false; 130 131 } 131 132 … … 137 138 u.asBytes.conversion = Array::AsIs; 138 139 u.asBytes.action = action; 140 u.asBytes.mayBeLargeTypedArray = false; 139 141 } 140 142 … … 146 148 u.asBytes.conversion = Array::AsIs; 147 149 u.asBytes.action = action; 148 } 149 150 ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action) 150 u.asBytes.mayBeLargeTypedArray = false; 151 } 152 153 ArrayMode(Array::Type type, Array::Class arrayClass, Array::Speculation speculation, Array::Conversion conversion, Array::Action action, bool mayBeLargeTypedArray = false) 151 154 { 152 155 u.asBytes.type = type; … … 155 158 u.asBytes.conversion = conversion; 156 159 u.asBytes.action = action; 160 u.asBytes.mayBeLargeTypedArray = mayBeLargeTypedArray; 157 161 } 158 162 … … 164 168 u.asBytes.conversion = conversion; 165 169 u.asBytes.action = action; 170 u.asBytes.mayBeLargeTypedArray = false; 166 171 } 167 172 … … 171 176 Array::Conversion conversion() const { return static_cast<Array::Conversion>(u.asBytes.conversion); } 172 177 Array::Action action() const { return static_cast<Array::Action>(u.asBytes.action); } 178 bool mayBeLargeTypedArray() const { return u.asBytes.mayBeLargeTypedArray; } 173 179 174 180 unsigned asWord() const { return u.asWord; } … … 180 186 181 187 static ArrayMode fromObserved(const ConcurrentJSLocker&, ArrayProfile*, Array::Action, bool makeSafe); 182 188 189 ArrayMode withType(Array::Type type) const 190 { 191 return ArrayMode(type, arrayClass(), speculation(), conversion(), action(), mayBeLargeTypedArray()); 192 } 193 183 194 ArrayMode withSpeculation(Array::Speculation speculation) const 184 195 { 185 return ArrayMode(type(), arrayClass(), speculation, conversion(), action()); 186 } 187 188 ArrayMode withArrayClass(Array::Class arrayClass) const 189 { 190 return ArrayMode(type(), arrayClass, speculation(), conversion(), action()); 191 } 192 196 return ArrayMode(type(), arrayClass(), speculation, conversion(), action(), mayBeLargeTypedArray()); 197 } 198 199 ArrayMode withConversion(Array::Conversion conversion) const 200 { 201 return ArrayMode(type(), arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray()); 202 } 203 204 ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const 205 { 206 return ArrayMode(type, arrayClass(), speculation(), conversion, action(), mayBeLargeTypedArray()); 207 } 208 209 ArrayMode withArrayClassAndSpeculationAndMayBeLargeTypedArray(Array::Class arrayClass, Array::Speculation speculation, bool mayBeLargeTypedArray) const 210 { 211 return ArrayMode(type(), arrayClass, speculation, conversion(), action(), mayBeLargeTypedArray); 212 } 213 214 static Array::Speculation speculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) 215 { 216 if (makeSafe) 217 return Array::OutOfBounds; 218 else if (profile->mayStoreToHole(locker)) 219 return Array::ToHole; 220 else 221 return Array::InBounds; 222 } 223 193 224 ArrayMode withSpeculationFromProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const 194 225 { 195 Array::Speculation mySpeculation; 196 197 if (makeSafe) 198 mySpeculation = Array::OutOfBounds; 199 else if (profile->mayStoreToHole(locker)) 200 mySpeculation = Array::ToHole; 201 else 202 mySpeculation = Array::InBounds; 203 204 return withSpeculation(mySpeculation); 205 } 206 226 return withSpeculation(speculationFromProfile(locker, profile, makeSafe)); 227 } 228 207 229 ArrayMode withProfile(const ConcurrentJSLocker& locker, ArrayProfile* profile, bool makeSafe) const 208 230 { 209 231 Array::Class myArrayClass; 210 211 232 if (isJSArray()) { 212 233 if (profile->usesOriginalArrayStructures(locker) && benefitsFromOriginalArray()) { … … 222 243 } else 223 244 myArrayClass = arrayClass(); 224 225 return withArrayClass(myArrayClass).withSpeculationFromProfile(locker, profile, makeSafe); 226 } 227 228 ArrayMode withType(Array::Type type) const 229 { 230 return ArrayMode(type, arrayClass(), speculation(), conversion(), action()); 231 } 232 233 ArrayMode withConversion(Array::Conversion conversion) const 234 { 235 return ArrayMode(type(), arrayClass(), speculation(), conversion, action()); 236 } 237 238 ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const 239 { 240 return ArrayMode(type, arrayClass(), speculation(), conversion, action()); 245 246 Array::Speculation speculation = speculationFromProfile(locker, profile, makeSafe); 247 248 bool largeTypedArray = profile->mayBeLargeTypedArray(locker); 249 250 return withArrayClassAndSpeculationAndMayBeLargeTypedArray(myArrayClass, speculation, largeTypedArray); 241 251 } 242 252 … … 527 537 && arrayClass() == other.arrayClass() 528 538 && speculation() == other.speculation() 529 && conversion() == other.conversion(); 539 && conversion() == other.conversion() 540 && mayBeLargeTypedArray() == other.mayBeLargeTypedArray(); 530 541 } 531 542 … … 580 591 uint8_t speculation; 581 592 uint8_t conversion : 4; 582 uint8_t action : 4; 593 uint8_t action : 1; 594 uint8_t mayBeLargeTypedArray : 1; 583 595 } asBytes; 584 596 unsigned asWord; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r284237 r284330 3808 3808 bool ByteCodeParser::handleIntrinsicGetter(Operand result, SpeculatedType prediction, const GetByVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks) 3809 3809 { 3810 #if USE(LARGE_TYPED_ARRAYS) 3811 static_assert(enableInt52()); 3812 #endif 3813 3810 3814 switch (variant.intrinsic()) { 3811 3815 case TypedArrayByteLengthIntrinsic: { 3816 bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow); 3817 #if !USE(LARGE_TYPED_ARRAYS) 3818 if (willNeedGetTypedArrayLengthAsInt52) 3819 return false; 3820 #endif 3812 3821 insertChecks(); 3813 3822 … … 3823 3832 }); 3824 3833 3825 Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode); 3834 NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength; 3835 Node* lengthNode = addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode); 3826 3836 // Our ArrayMode shouldn't cause us to exit here so we should be ok to exit without effects. 3827 3837 m_exitOK = true; 3828 3838 addToGraph(ExitOK); 3829 3839 3830 3831 3840 if (!logSize) { 3832 3841 set(result, lengthNode); … … 3834 3843 } 3835 3844 3836 // We can use a BitLShift here because typed arrays will never have a byteLength 3837 // that overflows int32. 3838 Node* shiftNode = jsConstant(jsNumber(logSize)); 3839 set(result, addToGraph(ArithBitLShift, lengthNode, shiftNode)); 3845 // We cannot use a BitLShift here because typed arrays may have a byteLength that overflows Int32. 3846 Node* typeSize = jsConstant(jsNumber(1 << logSize)); 3847 set(result, addToGraph(ArithMul, lengthNode, typeSize)); 3840 3848 3841 3849 return true; … … 3843 3851 3844 3852 case TypedArrayLengthIntrinsic: { 3853 bool willNeedGetTypedArrayLengthAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow); 3854 #if !USE(LARGE_TYPED_ARRAYS) 3855 if (willNeedGetTypedArrayLengthAsInt52) 3856 return false; 3857 #endif 3845 3858 insertChecks(); 3846 3859 … … 3854 3867 }); 3855 3868 3856 set(result, addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode)); 3869 NodeType op = willNeedGetTypedArrayLengthAsInt52 ? GetTypedArrayLengthAsInt52 : GetArrayLength; 3870 set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode)); 3857 3871 3858 3872 return true; … … 3861 3875 3862 3876 case TypedArrayByteOffsetIntrinsic: { 3877 bool willNeedGetTypedArrayByteOffsetAsInt52 = !isInt32Speculation(prediction) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow); 3878 #if !USE(LARGE_TYPED_ARRAYS) 3879 if (willNeedGetTypedArrayByteOffsetAsInt52) 3880 return false; 3881 #endif 3863 3882 insertChecks(); 3864 3883 … … 3872 3891 }); 3873 3892 3874 set(result, addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode)); 3893 NodeType op = willNeedGetTypedArrayByteOffsetAsInt52 ? GetTypedArrayByteOffsetAsInt52 : GetTypedArrayByteOffset; 3894 set(result, addToGraph(op, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode)); 3875 3895 3876 3896 return true; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2013-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 154 154 case GetIndexedPropertyStorage: 155 155 case GetArrayLength: 156 case GetTypedArrayLengthAsInt52: 156 157 case GetVectorLength: 157 158 case InByVal: … … 240 241 case LogicalNot: 241 242 case CheckInBounds: 243 case CheckInBoundsInt52: 242 244 case DoubleRep: 243 245 case ValueRep: … … 1338 1340 return; 1339 1341 1342 case GetTypedArrayByteOffsetAsInt52: 1343 read(MiscFields); 1344 def(HeapLocation(TypedArrayByteOffsetInt52Loc, MiscFields, node->child1()), LazyNode(node)); 1345 return; 1346 1340 1347 case GetPrototypeOf: { 1341 1348 switch (node->child1().useKind()) { … … 1443 1450 return; 1444 1451 } 1452 } 1453 1454 case GetTypedArrayLengthAsInt52: { 1455 ArrayMode mode = node->arrayMode(); 1456 RELEASE_ASSERT(mode.isSomeTypedArrayView()); 1457 read(MiscFields); 1458 def(HeapLocation(TypedArrayLengthInt52Loc, MiscFields, node->child1()), LazyNode(node)); 1459 return; 1445 1460 } 1446 1461 -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r284237 r284330 93 93 } 94 94 95 inline bool enableInt52()95 inline bool constexpr enableInt52() 96 96 { 97 97 #if USE(JSVALUE64) -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r284237 r284330 388 388 break; 389 389 } 390 case CheckInBoundsInt52: 391 break; 390 392 391 393 case GetMyArgumentByVal: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r284237 r284330 186 186 case AssertInBounds: 187 187 case CheckInBounds: 188 case CheckInBoundsInt52: 188 189 case ConstantStoragePointer: 189 190 case Check: … … 198 199 case GetSetter: 199 200 case GetArrayLength: 201 case GetTypedArrayLengthAsInt52: 200 202 case GetVectorLength: 201 203 case StringCharCodeAt: 202 204 case StringCodePointAt: 203 205 case GetTypedArrayByteOffset: 206 case GetTypedArrayByteOffsetAsInt52: 204 207 case GetPrototypeOf: 205 208 case PutStructure: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2012-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2012-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 1044 1044 && node->arrayMode().isSpecific() 1045 1045 && node->arrayMode().isInBounds() 1046 && !node->arrayMode().mayBeLargeTypedArray() 1046 1047 && !m_graph.hasExitSite(node->origin.semantic, Overflow)) { 1047 1048 … … 1074 1075 case Array::ForceExit: { 1075 1076 // Don't force OSR because we have only seen OwnStructureMode. 1076 // FIXME: W Eshould have a better way to do this...1077 // FIXME: We should have a better way to do this... 1077 1078 if (node->op() == EnumeratorGetByVal) 1078 1079 node->setArrayMode(node->arrayMode().withType(Array::Generic)); … … 1134 1135 fixEdge<Int32Use>(m_graph.varArgChild(node, 1)); 1135 1136 break; 1137 case Array::Int8Array: 1138 case Array::Int16Array: 1139 case Array::Int32Array: 1140 case Array::Uint8Array: 1141 case Array::Uint8ClampedArray: 1142 case Array::Uint16Array: 1143 case Array::Uint32Array: 1144 case Array::Float32Array: 1145 case Array::Float64Array: 1146 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0)); 1147 fixEdge<Int32Use>(m_graph.varArgChild(node, 1)); 1148 break; 1136 1149 default: 1137 1150 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0)); … … 1185 1198 && node->arrayMode().isSpecific() 1186 1199 && node->arrayMode().isInBounds() 1200 && !node->arrayMode().mayBeLargeTypedArray() 1187 1201 && !m_graph.hasExitSite(node->origin.semantic, Overflow)) { 1188 1202 … … 1718 1732 case NewTypedArray: { 1719 1733 watchHavingABadTime(node); 1720 1721 1734 if (node->child1()->shouldSpeculateInt32()) { 1722 1735 fixEdge<Int32Use>(node->child1()); 1736 node->clearFlags(NodeMustGenerate); 1737 break; 1738 } 1739 if (node->child1()->shouldSpeculateInt52()) { 1740 fixEdge<Int52RepUse>(node->child1()); 1723 1741 node->clearFlags(NodeMustGenerate); 1724 1742 break; … … 2150 2168 } 2151 2169 2170 case GetTypedArrayLengthAsInt52: { 2171 ArrayMode arrayMode = node->arrayMode().refine(m_graph, node, node->child1()->prediction(), ArrayMode::unusedIndexSpeculatedType); 2172 ASSERT(arrayMode.isSomeTypedArrayView()); 2173 node->setArrayMode(arrayMode); 2174 blessArrayOperation(node->child1(), Edge(), node->child2(), lengthNeedsStorage); 2175 2176 fixEdge<KnownCellUse>(node->child1()); 2177 node->setResult(NodeResultInt52); 2178 break; 2179 } 2180 2181 case GetTypedArrayByteOffsetAsInt52: { 2182 fixEdge<KnownCellUse>(node->child1()); 2183 node->setResult(NodeResultInt52); 2184 break; 2185 } 2186 2152 2187 case GetTypedArrayByteOffset: { 2153 2188 fixEdge<KnownCellUse>(node->child1()); … … 2183 2218 case AssertInBounds: 2184 2219 case CheckInBounds: 2220 case CheckInBoundsInt52: 2185 2221 case ConstantStoragePointer: 2186 2222 case DoubleAsInt32: … … 4097 4133 node->child2() = Edge(storage); 4098 4134 } 4099 4100 Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)4101 {4102 Node* storage = checkArray(arrayMode, origin, child, nullptr, lengthNeedsStorage);4103 return m_insertionSet.insertNode(4104 m_indexInBlock, SpecInt32Only, GetArrayLength, origin,4105 OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));4106 }4107 4135 4108 4136 void convertToHasIndexedProperty(Node* node) -
trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
r284237 r284330 40 40 // Can provide information as to whether a value is in machine registers, and if so which, 41 41 // whether a value has been spilled to the RegisterFile, and if so may be able to provide 42 // details of the format in memory (all values are spilled in a boxed form, but we may be 43 // able to track the type of box), and tracks how many outstanding uses of a value remain, 42 // details of the format in memory, and tracks how many outstanding uses of a value remain, 44 43 // so that we know when the value is dead and the machine registers associated with it 45 44 // may be released. -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
r284237 r284330 183 183 return; 184 184 185 case TypedArrayByteOffsetInt52Loc: 186 out.print("TypedArrayByteOffsetInt52Loc"); 187 return; 188 189 case TypedArrayLengthInt52Loc: 190 out.print("TypedArrayLengthInt52Loc"); 191 return; 192 185 193 case PrototypeLoc: 186 194 out.print("PrototypeLoc"); -
trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h
r284237 r284330 68 68 StructureLoc, 69 69 TypedArrayByteOffsetLoc, 70 TypedArrayByteOffsetInt52Loc, 71 TypedArrayLengthInt52Loc, 70 72 PrototypeLoc, 71 73 StackLoc, -
trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp
r284237 r284330 1336 1336 if (nonNegative && lessThanLength) { 1337 1337 executeNode(block->at(nodeIndex)); 1338 if (UNLIKELY(Options::validateBoundsCheckElimination()) )1338 if (UNLIKELY(Options::validateBoundsCheckElimination()) && node->op() == CheckInBounds) 1339 1339 m_insertionSet.insertNode(nodeIndex, SpecNone, AssertInBounds, node->origin, node->child1(), node->child2()); 1340 1340 // We just need to make sure we are a value-producing node. -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2011-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 1966 1966 case ArrayPop: 1967 1967 case GetArrayLength: 1968 case GetTypedArrayLengthAsInt52: 1968 1969 case HasIndexedProperty: 1969 1970 case EnumeratorNextUpdateIndexAndMode: … … 2005 2006 case ArrayPop: 2006 2007 case GetArrayLength: 2008 case GetTypedArrayLengthAsInt52: 2007 2009 return 2; 2008 2010 … … 2277 2279 case GetIndexedPropertyStorage: 2278 2280 case GetArrayLength: 2281 case GetTypedArrayLengthAsInt52: 2279 2282 case GetVectorLength: 2280 2283 case InByVal: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r284237 r284330 262 262 macro(MultiDeleteByOffset, NodeMustGenerate | NodeResultJS) \ 263 263 macro(GetArrayLength, NodeResultInt32) \ 264 /* This is only relevant for TypedArrays, as they are the only ones that can have a length that does not fit in 32 bits. */ \ 265 /* GetTypedArrayLengthAsInt52 and GetTypedArrayByteOffsetAsInt52 change to returning Int52 in Fixup. Doing it before causes validation failures. */ \ 266 macro(GetTypedArrayLengthAsInt52, NodeResultJS) \ 264 267 macro(GetVectorLength, NodeResultInt32) \ 265 268 macro(GetTypedArrayByteOffset, NodeResultInt32) \ 269 macro(GetTypedArrayByteOffsetAsInt52, NodeResultJS) \ 266 270 macro(GetScope, NodeResultJS) \ 267 271 macro(SkipScope, NodeResultJS) \ … … 287 291 macro(AssertInBounds, NodeMustGenerate) \ 288 292 macro(CheckInBounds, NodeMustGenerate | NodeResultJS) \ 293 macro(CheckInBoundsInt52, NodeMustGenerate | NodeResultJS) \ 289 294 macro(CheckIdent, NodeMustGenerate) \ 290 295 macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r284237 r284330 98 98 if (baseValue.isObject()) { 99 99 JSObject* object = asObject(baseValue); 100 if (object->canSetIndexQuickly(index, value)) { 101 object->setIndexQuickly(vm, index, value); 100 if (object->trySetIndexQuickly(vm, index, value)) 102 101 return; 103 }104 102 105 103 object->methodTable(vm)->putByIndex(object, globalObject, index, value, strict); … … 176 174 177 175 template<typename ViewClass> 178 char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, int 32_t size, char* vector)176 char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, intptr_t size, char* vector) 179 177 { 180 178 auto scope = DECLARE_THROW_SCOPE(vm); … … 184 182 return nullptr; 185 183 } 186 184 185 static_assert(std::numeric_limits<intptr_t>::max() <= std::numeric_limits<size_t>::max()); 186 size_t unsignedSize = static_cast<size_t>(size); 187 187 188 if (vector) 188 return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, size, untagArrayPtr(vector, size)));189 190 RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, size)));189 return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, unsignedSize, untagArrayPtr(vector, unsignedSize))); 190 191 RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, unsignedSize))); 191 192 } 192 193 … … 1909 1910 } 1910 1911 1911 JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1912 JSC_DEFINE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1912 1913 { 1913 1914 VM& vm = globalObject->vm(); … … 1925 1926 } 1926 1927 1927 JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1928 JSC_DEFINE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1928 1929 { 1929 1930 VM& vm = globalObject->vm(); … … 1941 1942 } 1942 1943 1943 JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1944 JSC_DEFINE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1944 1945 { 1945 1946 VM& vm = globalObject->vm(); … … 1957 1958 } 1958 1959 1959 JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1960 JSC_DEFINE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1960 1961 { 1961 1962 VM& vm = globalObject->vm(); … … 1973 1974 } 1974 1975 1975 JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1976 JSC_DEFINE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1976 1977 { 1977 1978 VM& vm = globalObject->vm(); … … 1989 1990 } 1990 1991 1991 JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))1992 JSC_DEFINE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 1992 1993 { 1993 1994 VM& vm = globalObject->vm(); … … 2005 2006 } 2006 2007 2007 JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))2008 JSC_DEFINE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 2008 2009 { 2009 2010 VM& vm = globalObject->vm(); … … 2021 2022 } 2022 2023 2023 JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))2024 JSC_DEFINE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 2024 2025 { 2025 2026 VM& vm = globalObject->vm(); … … 2037 2038 } 2038 2039 2039 JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))2040 JSC_DEFINE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 2040 2041 { 2041 2042 VM& vm = globalObject->vm(); … … 2053 2054 } 2054 2055 2055 JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))2056 JSC_DEFINE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 2056 2057 { 2057 2058 VM& vm = globalObject->vm(); … … 2069 2070 } 2070 2071 2071 JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, int 32_t length, char* vector))2072 JSC_DEFINE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject* globalObject, Structure* structure, intptr_t length, char* vector)) 2072 2073 { 2073 2074 VM& vm = globalObject->vm(); -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r284237 r284330 120 120 JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSize, char*, (JSGlobalObject*, Structure*, int32_t, Butterfly*)); 121 121 JSC_DECLARE_JIT_OPERATION(operationNewArrayWithSizeAndHint, char*, (JSGlobalObject*, Structure*, int32_t, int32_t, Butterfly*)); 122 JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));122 JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 123 123 JSC_DECLARE_JIT_OPERATION(operationNewInt8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 124 JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));124 JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 125 125 JSC_DECLARE_JIT_OPERATION(operationNewInt16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 126 JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));126 JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 127 127 JSC_DECLARE_JIT_OPERATION(operationNewInt32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 128 JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));128 JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 129 129 JSC_DECLARE_JIT_OPERATION(operationNewUint8ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 130 JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));130 JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 131 131 JSC_DECLARE_JIT_OPERATION(operationNewUint8ClampedArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 132 JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));132 JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 133 133 JSC_DECLARE_JIT_OPERATION(operationNewUint16ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 134 JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));134 JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 135 135 JSC_DECLARE_JIT_OPERATION(operationNewUint32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 136 JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));136 JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 137 137 JSC_DECLARE_JIT_OPERATION(operationNewFloat32ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 138 JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));138 JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 139 139 JSC_DECLARE_JIT_OPERATION(operationNewFloat64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 140 JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));140 JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 141 141 JSC_DECLARE_JIT_OPERATION(operationNewBigInt64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 142 JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, int 32_t, char*));142 JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithSize, char*, (JSGlobalObject*, Structure*, intptr_t, char*)); 143 143 JSC_DECLARE_JIT_OPERATION(operationNewBigUint64ArrayWithOneArgument, char*, (JSGlobalObject*, Structure*, EncodedJSValue)); 144 144 JSC_DECLARE_JIT_OPERATION(operationNewArrayIterator, JSCell*, (VM*, Structure*)); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r284237 r284330 987 987 } 988 988 989 case GetTypedArrayLengthAsInt52: 990 case GetTypedArrayByteOffsetAsInt52: { 991 setPrediction(SpecInt52Any); 992 break; 993 } 994 989 995 case StringCharCodeAt: 990 996 case StringCodePointAt: { … … 1321 1327 case AssertInBounds: 1322 1328 case CheckInBounds: 1329 case CheckInBoundsInt52: 1323 1330 case ValueToInt32: 1324 1331 case DoubleRep: -
trunk/Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp
r284237 r284330 101 101 102 102 if (m_node->arrayMode().typedArrayType() != NotTypedArray && m_node->arrayMode().isOutOfBounds()) { 103 Node* length = m_insertionSet.insertNode( 104 m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin, 105 OpInfo(m_node->arrayMode().asWord()), base, storage); 106 107 m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use); 103 #if USE(LARGE_TYPED_ARRAYS) 104 if (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow)) { 105 Node* length = m_insertionSet.insertNode( 106 m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin, 107 OpInfo(m_node->arrayMode().asWord()), base, storage); 108 m_graph.varArgChild(m_node, 4) = Edge(length, Int52RepUse); 109 } else { 110 #endif 111 Node* length = m_insertionSet.insertNode( 112 m_nodeIndex, SpecInt32Only, GetArrayLength, m_node->origin, 113 OpInfo(m_node->arrayMode().asWord()), base, storage); 114 m_graph.varArgChild(m_node, 4) = Edge(length, KnownInt32Use); 115 #if USE(LARGE_TYPED_ARRAYS) 116 } 117 #endif 108 118 break; 109 119 } … … 138 148 } 139 149 140 Node* length = m_insertionSet.insertNode( 141 m_nodeIndex, SpecInt32Only, op, m_node->origin, 142 OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage); 143 Node* checkInBounds = m_insertionSet.insertNode( 144 m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin, 145 index, Edge(length, KnownInt32Use)); 150 Node* checkInBounds; 151 #if USE(LARGE_TYPED_ARRAYS) 152 if ((op == GetArrayLength) && (m_node->arrayMode().mayBeLargeTypedArray() || m_graph.hasExitSite(m_node->origin.semantic, Overflow))) { 153 Node* length = m_insertionSet.insertNode( 154 m_nodeIndex, SpecInt52Any, GetTypedArrayLengthAsInt52, m_node->origin, 155 OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage); 156 length->setResult(NodeResultInt52); 157 // The return type is a dummy since this node does not actually return anything. 158 checkInBounds = m_insertionSet.insertNode( 159 m_nodeIndex, SpecInt32Only, CheckInBoundsInt52, m_node->origin, 160 index, Edge(length, Int52RepUse)); 161 } else { 162 #endif 163 Node* length = m_insertionSet.insertNode( 164 m_nodeIndex, SpecInt32Only, op, m_node->origin, 165 OpInfo(m_node->arrayMode().asWord()), Edge(base.node(), KnownCellUse), storage); 166 checkInBounds = m_insertionSet.insertNode( 167 m_nodeIndex, SpecInt32Only, CheckInBounds, m_node->origin, 168 index, Edge(length, KnownInt32Use)); 169 #if USE(LARGE_TYPED_ARRAYS) 170 } 171 #endif 172 146 173 147 174 AdjacencyList adjacencyList = m_graph.copyVarargChildren(m_node); -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r284237 r284330 289 289 case AssertInBounds: 290 290 case CheckInBounds: 291 case CheckInBoundsInt52: 291 292 case ConstantStoragePointer: 292 293 case Check: … … 374 375 case GetIndexedPropertyStorage: 375 376 case GetArrayLength: 377 case GetTypedArrayLengthAsInt52: 376 378 case GetVectorLength: 377 379 case ArrayPop: … … 386 388 case CheckDetached: 387 389 case GetTypedArrayByteOffset: 390 case GetTypedArrayByteOffsetAsInt52: 388 391 return !(state.forNode(node->child1()).m_type & ~(SpecTypedArrayView)); 389 392 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r284237 r284330 3239 3239 } 3240 3240 3241 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR )3241 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR) 3242 3242 { 3243 3243 if (node->op() == PutByValAlias) … … 3246 3246 m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode()); 3247 3247 if (view) { 3248 uint32_t length = view->length();3248 size_t length = view->length(); 3249 3249 Node* indexNode = m_jit.graph().child(node, 1).node(); 3250 if (indexNode->is Int32Constant() && indexNode->asUInt32() < length)3250 if (indexNode->isAnyIntConstant() && indexNode->asUInt32() < length) 3251 3251 return JITCompiler::Jump(); 3252 #if USE(LARGE_TYPED_ARRAYS) 3253 m_jit.signExtend32ToPtr(indexGPR, scratchGPR); 3254 return m_jit.branch64( 3255 MacroAssembler::AboveOrEqual, scratchGPR, MacroAssembler::Imm64(length)); 3256 #else 3257 UNUSED_PARAM(scratchGPR); 3252 3258 return m_jit.branch32( 3253 3259 MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length)); 3254 } 3260 #endif 3261 } 3262 3263 #if USE(LARGE_TYPED_ARRAYS) 3264 m_jit.signExtend32ToPtr(indexGPR, scratchGPR); 3265 return m_jit.branch64( 3266 MacroAssembler::AboveOrEqual, scratchGPR, 3267 MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength())); 3268 #else 3255 3269 return m_jit.branch32( 3256 3270 MacroAssembler::AboveOrEqual, indexGPR, 3257 3271 MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength())); 3258 } 3259 3260 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR) 3261 { 3262 JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR); 3272 #endif 3273 } 3274 3275 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR) 3276 { 3277 JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR, scratchGPR); 3263 3278 if (!jump.isSet()) 3264 3279 return; … … 3381 3396 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 3382 3397 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 3398 GPRTemporary scratch(this); 3383 3399 3384 3400 GPRReg baseReg = base.gpr(); 3385 3401 GPRReg propertyReg = property.gpr(); 3386 3402 GPRReg storageReg = storage.gpr(); 3403 GPRReg scratchGPR = scratch.gpr(); 3387 3404 3388 3405 std::optional<FPRTemporary> fprTemp; … … 3398 3415 bool shouldBox = format == DataFormatJS; 3399 3416 3400 emitTypedArrayBoundsCheck(node, baseReg, propertyReg );3417 emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR); 3401 3418 loadFromIntTypedArray(storageReg, propertyReg, resultRegs.payloadGPR(), type); 3402 3419 constexpr bool canSpeculate = true; … … 3556 3573 3557 3574 StorageOperand storage(this, m_jit.graph().varArgChild(node, 3)); 3575 GPRTemporary scratch(this); 3558 3576 GPRReg storageReg = storage.gpr(); 3559 3577 … … 3588 3606 ASSERT(valueGPR != base); 3589 3607 ASSERT(valueGPR != storageReg); 3590 JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property );3608 JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratch.gpr()); 3591 3609 3592 3610 switch (elementSize(type)) { … … 3646 3664 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1)); 3647 3665 StorageOperand storage(this, m_graph.varArgChild(node, 2)); 3666 GPRTemporary scratch(this); 3648 3667 3649 3668 GPRReg baseReg = base.gpr(); 3650 3669 GPRReg propertyReg = property.gpr(); 3651 3670 GPRReg storageReg = storage.gpr(); 3671 GPRReg scratchGPR = scratch.gpr(); 3652 3672 3653 3673 JSValueRegs resultRegs; … … 3657 3677 FPRTemporary result(this); 3658 3678 FPRReg resultReg = result.fpr(); 3659 emitTypedArrayBoundsCheck(node, baseReg, propertyReg );3679 emitTypedArrayBoundsCheck(node, baseReg, propertyReg, scratchGPR); 3660 3680 switch (elementSize(type)) { 3661 3681 case 4: … … 3691 3711 SpeculateDoubleOperand valueOp(this, valueUse); 3692 3712 FPRTemporary scratch(this); 3713 GPRTemporary gpScratch(this); 3693 3714 FPRReg valueFPR = valueOp.fpr(); 3694 3715 FPRReg scratchFPR = scratch.fpr(); 3695 3696 MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property); 3716 GPRReg scratchGPR = gpScratch.gpr(); 3717 3718 MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property, scratchGPR); 3697 3719 3698 3720 switch (elementSize(type)) { … … 7968 7990 auto untagArrayPtr = [&]() { 7969 7991 #if CPU(ARM64E) 7970 m_jit.untagArrayPtrLength 32(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth);7992 m_jit.untagArrayPtrLength64(MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfLength()), storageReg, validateAuth); 7971 7993 #else 7972 7994 UNUSED_PARAM(validateAuth); … … 8040 8062 GPRReg vectorGPR = vector.gpr(); 8041 8063 GPRReg dataGPR = data.gpr(); 8042 ASSERT(baseGPR != vectorGPR);8043 ASSERT(baseGPR != dataGPR);8044 ASSERT(vectorGPR != dataGPR);8045 8064 8046 8065 GPRReg arrayBufferGPR = dataGPR; … … 8082 8101 ASSERT(!JSArrayBufferView::nullVectorPtr()); 8083 8102 nullVector.link(&m_jit); 8103 #endif 8104 8105 #if USE(LARGE_TYPED_ARRAYS) 8106 // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here. 8107 speculationCheck(Overflow, JSValueRegs(), nullptr, m_jit.branch32(MacroAssembler::Above, vectorGPR, TrustedImm32(std::numeric_limits<int32_t>::max()))); 8084 8108 #endif 8085 8109 … … 8350 8374 GPRReg baseGPR = base.gpr(); 8351 8375 GPRReg resultGPR = result.gpr(); 8376 #if USE(LARGE_TYPED_ARRAYS) 8377 m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR); 8378 speculationCheck(Overflow, JSValueSource(), nullptr, m_jit.branch64(MacroAssembler::Above, resultGPR, TrustedImm64(std::numeric_limits<int32_t>::max()))); 8379 #else 8352 8380 m_jit.load32(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR); 8381 #endif 8353 8382 strictInt32Result(resultGPR, node); 8354 8383 break; 8355 8384 } } 8356 8385 } 8386 8357 8387 8358 8388 void SpeculativeJIT::compileCheckIdent(Node* node) … … 11120 11150 RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType)); 11121 11151 RELEASE_ASSERT(structure.get()); 11122 11152 11153 #if USE(LARGE_TYPED_ARRAYS) 11154 // The operations we call on the slow path expect a intptr_t, so int64_t on 64 bit platforms 11155 SpeculateInt32Operand size(this, node->child1()); 11156 GPRTemporary scratch(this); 11157 GPRReg sizeGPR = size.gpr(); 11158 GPRReg scratchGPR = scratch.gpr(); 11159 m_jit.signExtend32ToPtr(sizeGPR, scratchGPR); 11160 emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, scratchGPR); 11161 #else 11123 11162 SpeculateInt32Operand size(this, node->child1()); 11124 11163 GPRReg sizeGPR = size.gpr(); 11125 11164 emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR); 11165 #endif 11166 } 11167 11168 void SpeculativeJIT::emitNewTypedArrayWithSizeInRegister(Node* node, TypedArrayType typedArrayType, RegisteredStructure structure, GPRReg sizeGPR) 11169 { 11126 11170 GPRTemporary result(this); 11127 11171 GPRTemporary storage(this); … … 11137 11181 m_jit.move(TrustedImmPtr(nullptr), storageGPR); 11138 11182 11183 #if USE(LARGE_TYPED_ARRAYS) 11184 slowCases.append(m_jit.branch64( 11185 MacroAssembler::Above, sizeGPR, TrustedImm64(JSArrayBufferView::fastSizeLimit))); 11186 // We assume through the rest of the fast path that the size is a 32-bit number. 11187 static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit)); 11188 #else 11139 11189 slowCases.append(m_jit.branch32( 11140 11190 MacroAssembler::Above, sizeGPR, TrustedImm32(JSArrayBufferView::fastSizeLimit))); 11191 #endif 11141 11192 11142 11193 m_jit.move(sizeGPR, scratchGPR); … … 11194 11245 storageGPR, 11195 11246 MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfVector())); 11247 #if USE(LARGE_TYPED_ARRAYS) 11248 m_jit.store64( 11249 sizeGPR, 11250 MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength())); 11251 #else 11196 11252 m_jit.store32( 11197 11253 sizeGPR, 11198 11254 MacroAssembler::Address(resultGPR, JSArrayBufferView::offsetOfLength())); 11255 #endif 11199 11256 m_jit.store32( 11200 11257 TrustedImm32(FastTypedArray), … … 14168 14225 compileNewTypedArrayWithSize(node); 14169 14226 break; 14227 #if USE(LARGE_TYPED_ARRAYS) 14228 case Int52RepUse: 14229 compileNewTypedArrayWithInt52Size(node); 14230 break; 14231 #endif 14170 14232 case UntypedUse: { 14171 14233 JSValueOperand argument(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2011-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 1301 1301 void compileNewStringObject(Node*); 1302 1302 void compileNewSymbol(Node*); 1303 1303 1304 void emitNewTypedArrayWithSizeInRegister(Node*, TypedArrayType, RegisteredStructure, GPRReg sizeGPR); 1304 1305 void compileNewTypedArrayWithSize(Node*); 1305 1306 #if USE(LARGE_TYPED_ARRAYS) 1307 void compileNewTypedArrayWithInt52Size(Node*); 1308 #endif 1309 1306 1310 void compileInt32Compare(Node*, MacroAssembler::RelationalCondition); 1307 1311 void compileInt52Compare(Node*, MacroAssembler::RelationalCondition); … … 1374 1378 1375 1379 void compileGetArrayLength(Node*); 1380 #if USE(LARGE_TYPED_ARRAYS) 1381 void compileGetTypedArrayLengthAsInt52(Node*); 1382 #endif 1376 1383 1377 1384 void compileCheckTypeInfoFlags(Node*); … … 1432 1439 void compileConstantStoragePointer(Node*); 1433 1440 void compileGetIndexedPropertyStorage(Node*); 1434 JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR );1441 JITCompiler::Jump jumpForTypedArrayOutOfBounds(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR); 1435 1442 JITCompiler::Jump jumpForTypedArrayIsDetachedIfOutOfBounds(Node*, GPRReg baseGPR, JITCompiler::Jump outOfBounds); 1436 void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR );1443 void emitTypedArrayBoundsCheck(Node*, GPRReg baseGPR, GPRReg indexGPR, GPRReg scratchGPR); 1437 1444 void compileGetTypedArrayByteOffset(Node*); 1445 #if USE(LARGE_TYPED_ARRAYS) 1446 void compileGetTypedArrayByteOffsetAsInt52(Node*); 1447 #endif 1438 1448 void compileGetByValOnIntTypedArray(Node*, TypedArrayType, const ScopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat preferredFormat)>& prefix); 1439 1449 void compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node*, TypedArrayType); … … 2428 2438 }; 2429 2439 2430 // Gives you a canonical Int52 (i.e. it's left-shifted by 1 6, low bits zero).2440 // Gives you a canonical Int52 (i.e. it's left-shifted by 12, low bits zero). 2431 2441 class SpeculateInt52Operand { 2432 2442 WTF_MAKE_FAST_ALLOCATED; … … 2476 2486 }; 2477 2487 2478 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16bits are sign-extended).2488 // Gives you a strict Int52 (i.e. the payload is in the low 52 bits, high 12 bits are sign-extended). 2479 2489 class SpeculateStrictInt52Operand { 2480 2490 WTF_MAKE_FAST_ALLOCATED; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r284255 r284330 2137 2137 break; 2138 2138 default: { 2139 ASSERT(node->arrayMode().isSomeTypedArrayView()); 2139 2140 TypedArrayType type = node->arrayMode().typedArrayType(); 2140 2141 if (isInt(type)) … … 3541 3542 break; 3542 3543 3544 case GetTypedArrayLengthAsInt52: 3545 // We do not support typed arrays larger than 2GB on 32-bit platforms. 3546 RELEASE_ASSERT_NOT_REACHED(); 3547 break; 3548 3543 3549 case DeleteById: { 3544 3550 compileDeleteById(node); … … 3620 3626 case GetTypedArrayByteOffset: { 3621 3627 compileGetTypedArrayByteOffset(node); 3628 break; 3629 } 3630 3631 case GetTypedArrayByteOffsetAsInt52: { 3632 RELEASE_ASSERT_NOT_REACHED(); 3622 3633 break; 3623 3634 } … … 4401 4412 case AssertInBounds: 4402 4413 case CheckInBounds: 4414 case CheckInBoundsInt52: 4403 4415 case ArithIMul: 4404 4416 case MultiGetByOffset: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2011-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 2694 2694 } } 2695 2695 } 2696 2697 #if USE(LARGE_TYPED_ARRAYS) 2698 void SpeculativeJIT::compileNewTypedArrayWithInt52Size(Node* node) 2699 { 2700 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic); 2701 auto typedArrayType = node->typedArrayType(); 2702 RegisteredStructure structure = m_jit.graph().registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType)); 2703 RELEASE_ASSERT(structure.get()); 2704 2705 SpeculateStrictInt52Operand size(this, node->child1()); 2706 GPRReg sizeGPR = size.gpr(); 2707 2708 emitNewTypedArrayWithSizeInRegister(node, typedArrayType, structure, sizeGPR); 2709 } 2710 2711 void SpeculativeJIT::compileGetTypedArrayLengthAsInt52(Node* node) 2712 { 2713 RELEASE_ASSERT(node->arrayMode().isSomeTypedArrayView()); 2714 SpeculateCellOperand base(this, node->child1()); 2715 GPRTemporary result(this, Reuse, base); 2716 GPRReg baseGPR = base.gpr(); 2717 GPRReg resultGPR = result.gpr(); 2718 m_jit.load64(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()), resultGPR); 2719 static_assert(MAX_ARRAY_BUFFER_SIZE < (1ull << 52), "there is a risk that the size of a typed array won't fit in an Int52"); 2720 strictInt52Result(resultGPR, node); 2721 } 2722 2723 void SpeculativeJIT::compileGetTypedArrayByteOffsetAsInt52(Node* node) 2724 { 2725 SpeculateCellOperand base(this, node->child1()); 2726 GPRTemporary vector(this); 2727 GPRTemporary data(this); 2728 2729 GPRReg baseGPR = base.gpr(); 2730 GPRReg vectorGPR = vector.gpr(); 2731 GPRReg dataGPR = data.gpr(); 2732 2733 GPRReg arrayBufferGPR = dataGPR; 2734 2735 JITCompiler::Jump emptyByteOffset = m_jit.branch32( 2736 MacroAssembler::NotEqual, 2737 MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfMode()), 2738 TrustedImm32(WastefulTypedArray)); 2739 2740 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR); 2741 2742 JITCompiler::Jump nullVector = m_jit.branchPtr(JITCompiler::Equal, vectorGPR, TrustedImmPtr(JSArrayBufferView::nullVectorPtr())); 2743 2744 m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR); 2745 m_jit.cageWithoutUntagging(Gigacage::JSValue, dataGPR); 2746 2747 cageTypedArrayStorage(baseGPR, vectorGPR); 2748 2749 m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), arrayBufferGPR); 2750 // FIXME: This needs caging. 2751 // https://bugs.webkit.org/show_bug.cgi?id=175515 2752 m_jit.loadPtr(MacroAssembler::Address(arrayBufferGPR, ArrayBuffer::offsetOfData()), dataGPR); 2753 #if CPU(ARM64E) 2754 m_jit.removeArrayPtrTag(dataGPR); 2755 #endif 2756 2757 m_jit.subPtr(dataGPR, vectorGPR); 2758 2759 JITCompiler::Jump done = m_jit.jump(); 2760 2761 #if CPU(ARM64E) 2762 nullVector.link(&m_jit); 2763 #endif 2764 emptyByteOffset.link(&m_jit); 2765 m_jit.move(TrustedImmPtr(nullptr), vectorGPR); 2766 2767 done.link(&m_jit); 2768 #if !CPU(ARM64E) 2769 ASSERT(!JSArrayBufferView::nullVectorPtr()); 2770 nullVector.link(&m_jit); 2771 #endif 2772 2773 strictInt52Result(vectorGPR, node); 2774 } 2775 #endif // USE(LARGE_TYPED_ARRAYS) 2696 2776 2697 2777 void SpeculativeJIT::compile(Node* node) … … 3645 3725 SpeculateCellOperand base(this, baseEdge); 3646 3726 SpeculateStrictInt32Operand index(this, indexEdge); 3727 GPRTemporary scratch (this); 3647 3728 3648 3729 baseGPR = base.gpr(); 3649 3730 indexGPR = index.gpr(); 3650 3731 3651 emitTypedArrayBoundsCheck(node, baseGPR, indexGPR );3732 emitTypedArrayBoundsCheck(node, baseGPR, indexGPR, scratch.gpr()); 3652 3733 3653 3734 GPRTemporary args[2]; … … 4382 4463 break; 4383 4464 4465 case GetTypedArrayLengthAsInt52: 4466 #if USE(ADDRESS64) 4467 compileGetTypedArrayLengthAsInt52(node); 4468 #else 4469 RELEASE_ASSERT_NOT_REACHED(); 4470 #endif 4471 break; 4472 4384 4473 case DeleteById: { 4385 4474 compileDeleteById(node); … … 4497 4586 case GetTypedArrayByteOffset: { 4498 4587 compileGetTypedArrayByteOffset(node); 4588 break; 4589 } 4590 4591 case GetTypedArrayByteOffsetAsInt52: { 4592 #if USE(LARGE_TYPED_ARRAYS) 4593 compileGetTypedArrayByteOffsetAsInt52(node); 4594 #else 4595 RELEASE_ASSERT_NOT_REACHED(); 4596 #endif 4499 4597 break; 4500 4598 } … … 5590 5688 if (data.byteSize > 1) 5591 5689 m_jit.add64(TrustedImm32(data.byteSize - 1), t2); 5690 #if USE(LARGE_TYPED_ARRAYS) 5691 speculationCheck(OutOfBounds, JSValueRegs(), node, 5692 m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0))); 5693 m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); 5694 #else 5695 // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after 5592 5696 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); 5697 #endif 5593 5698 speculationCheck(OutOfBounds, JSValueRegs(), node, 5594 5699 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1)); … … 5791 5896 if (data.byteSize > 1) 5792 5897 m_jit.add64(TrustedImm32(data.byteSize - 1), t2); 5898 #if USE(LARGE_TYPED_ARRAYS) 5899 speculationCheck(OutOfBounds, JSValueRegs(), node, 5900 m_jit.branch32(MacroAssembler::LessThan, indexGPR, TrustedImm32(0))); 5901 m_jit.load64(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); 5902 #else 5903 // No need for an explicit check against 0 here, negative indices are caught by the comparison with length right after 5793 5904 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1); 5905 #endif 5794 5906 speculationCheck(OutOfBounds, JSValueRegs(), node, 5795 5907 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1)); … … 6043 6155 case AssertInBounds: 6044 6156 case CheckInBounds: 6157 case CheckInBoundsInt52: 6045 6158 case ArithIMul: 6046 6159 case MultiGetByOffset: -
trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
r284237 r284330 280 280 case PutByValAlias: 281 281 case GetArrayLength: 282 case GetTypedArrayLengthAsInt52: 282 283 case CheckArray: 283 284 case CheckDetached: 284 285 case GetIndexedPropertyStorage: 285 286 case GetTypedArrayByteOffset: 287 case GetTypedArrayByteOffsetAsInt52: 286 288 case Phantom: 287 289 case MovHint: … … 360 362 case PutByValAlias: 361 363 case GetArrayLength: 364 case GetTypedArrayLengthAsInt52: 362 365 case GetIndexedPropertyStorage: 363 366 case Phantom: -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r284237 r284330 641 641 case AssertInBounds: 642 642 case CheckInBounds: 643 case CheckInBoundsInt52: 643 644 case PhantomNewObject: 644 645 case PhantomNewFunction: -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r284237 r284330 171 171 case NukeStructureAndSetButterfly: 172 172 case GetTypedArrayByteOffset: 173 case GetTypedArrayByteOffsetAsInt52: 173 174 case GetPrototypeOf: 174 175 case NotifyWrite: … … 200 201 case AssertInBounds: 201 202 case CheckInBounds: 203 case CheckInBoundsInt52: 202 204 case ConstantStoragePointer: 203 205 case Check: … … 392 394 case CPUIntrinsic: 393 395 case GetArrayLength: 396 case GetTypedArrayLengthAsInt52: 394 397 case GetVectorLength: 395 398 case GetByVal: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r284237 r284330 606 606 if (node->op() == CheckInBounds) 607 607 continue; 608 if (node->op() == CheckInBoundsInt52) 609 continue; 608 610 609 611 AbstractValue value = m_interpreter.forNode(node); … … 1026 1028 compileGetArrayLength(); 1027 1029 break; 1030 case GetTypedArrayLengthAsInt52: 1031 compileGetTypedArrayLengthAsInt52(); 1032 break; 1028 1033 case GetVectorLength: 1029 1034 compileGetVectorLength(); … … 1034 1039 case CheckInBounds: 1035 1040 compileCheckInBounds(); 1041 break; 1042 case CheckInBoundsInt52: 1043 compileCheckInBoundsInt52(); 1036 1044 break; 1037 1045 case GetByVal: … … 1175 1183 case GetTypedArrayByteOffset: 1176 1184 compileGetTypedArrayByteOffset(); 1185 break; 1186 case GetTypedArrayByteOffsetAsInt52: 1187 compileGetTypedArrayByteOffsetAsInt52(); 1177 1188 break; 1178 1189 case GetPrototypeOf: … … 4829 4840 } 4830 4841 4831 void compileGetTypedArrayByteOffset()4832 { 4833 LValue basePtr = lowCell(m_node->child1()); 4842 LValue emitGetTypedArrayByteOffsetExceptSettingResult() 4843 { 4844 LValue basePtr = lowCell(m_node->child1()); 4834 4845 4835 4846 LBasicBlock wastefulCase = m_out.newBlock(); … … 4847 4858 4848 4859 LValue vector = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector); 4849 m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())), 4860 m_out.branch(m_out.equal(vector, m_out.constIntPtr(JSArrayBufferView::nullVectorPtr())), 4850 4861 unsure(continuation), unsure(notNull)); 4851 4862 … … 4867 4878 m_out.appendTo(continuation, lastNext); 4868 4879 4869 setInt32(m_out.castToInt32(m_out.phi(pointerType(), nullVectorOut, wastefulOut))); 4870 } 4880 return m_out.phi(pointerType(), nullVectorOut, wastefulOut); 4881 } 4882 4883 void compileGetTypedArrayByteOffset() 4884 { 4885 LValue result = emitGetTypedArrayByteOffsetExceptSettingResult(); 4886 #if USE(LARGE_TYPED_ARRAYS) 4887 // AI promises that the result of GetTypedArrayByteOffset will be Int32, so we must uphold that promise here. 4888 speculate(Overflow, noValue(), nullptr, m_out.above(result, m_out.constInt64(std::numeric_limits<int32_t>::max()))); 4889 #endif 4890 setInt32(m_out.castToInt32(result)); 4891 } 4892 4893 IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn") 4894 void compileGetTypedArrayByteOffsetAsInt52() 4895 { 4896 // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent. 4897 RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t)); 4898 LValue result = emitGetTypedArrayByteOffsetExceptSettingResult(); 4899 setStrictInt52(result); 4900 } 4901 IGNORE_CLANG_WARNINGS_END 4871 4902 4872 4903 void compileGetPrototypeOf() … … 5055 5086 default: 5056 5087 if (m_node->arrayMode().isSomeTypedArrayView()) { 5057 setInt32( 5058 m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); 5088 #if USE(LARGE_TYPED_ARRAYS) 5089 LValue length = m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length); 5090 speculate(Overflow, noValue(), nullptr, m_out.above(length, m_out.constInt64(std::numeric_limits<int32_t>::max()))); 5091 setInt32(m_out.castToInt32(length)); 5092 #else 5093 setInt32(m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); 5094 #endif 5059 5095 return; 5060 5096 } … … 5064 5100 } 5065 5101 } 5102 5103 IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn") 5104 void compileGetTypedArrayLengthAsInt52() 5105 { 5106 RELEASE_ASSERT(m_node->arrayMode().isSomeTypedArrayView()); 5107 // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent. 5108 RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t)); 5109 setStrictInt52(m_out.load64NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length)); 5110 } 5111 IGNORE_CLANG_WARNINGS_END 5066 5112 5067 5113 void compileGetVectorLength() … … 5109 5155 // we dominate them. 5110 5156 } 5111 5157 5158 IGNORE_CLANG_WARNINGS_BEGIN("missing-noreturn") 5159 void compileCheckInBoundsInt52() 5160 { 5161 // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent. 5162 RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t)); 5163 // Sign-extended to also catch negative indices 5164 LValue index = m_out.signExt32To64(lowInt32(m_node->child1())); 5165 LValue length = lowStrictInt52(m_node->child2()); 5166 speculate(OutOfBounds, noValue(), nullptr, m_out.aboveOrEqual(index, length)); 5167 // Even though we claim to have JSValue result, no user of us should 5168 // depend on our value. Users of this node just need to maintain that 5169 // we dominate them. 5170 } 5171 IGNORE_CLANG_WARNINGS_END 5172 5112 5173 LValue compileGetByValImpl() 5113 5174 { … … 6009 6070 LBasicBlock isOutOfBounds = m_out.newBlock(); 6010 6071 LBasicBlock continuation = m_out.newBlock(); 6011 6012 m_out.branch( 6013 m_out.aboveOrEqual(index, lowInt32(child5)), 6014 unsure(isOutOfBounds), unsure(isInBounds)); 6015 6072 6073 LValue isOutOfBoundsCondition; 6074 if (child5.useKind() == Int52RepUse) { 6075 // The preprocessor chokes on RELEASE_ASSERT(USE(LARGE_TYPED_ARRAYS)), this is equivalent. 6076 RELEASE_ASSERT(sizeof(size_t) == sizeof(uint64_t)); 6077 isOutOfBoundsCondition = m_out.aboveOrEqual(m_out.signExt32To64(index), lowStrictInt52(child5)); 6078 } else { 6079 ASSERT(child5.useKind() == Int32Use); 6080 isOutOfBoundsCondition = m_out.aboveOrEqual(index, lowInt32(child5)); 6081 } 6082 m_out.branch(isOutOfBoundsCondition, unsure(isOutOfBounds), unsure(isInBounds)); 6083 6016 6084 LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds); 6017 6085 m_out.store(valueToStore, pointer, storeType(type)); … … 8170 8238 RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType)); 8171 8239 8172 LValue size = lowInt32(m_node->child1()); 8173 8174 LBasicBlock smallEnoughCase = m_out.newBlock(); 8175 LBasicBlock slowCase = m_out.newBlock(); 8176 LBasicBlock continuation = m_out.newBlock(); 8177 8178 ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero); 8179 8180 m_out.branch( 8181 m_out.above(size, m_out.constInt32(JSArrayBufferView::fastSizeLimit)), 8182 rarely(slowCase), usually(smallEnoughCase)); 8183 8184 LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase); 8185 8186 LValue byteSize = 8187 m_out.shl(m_out.zeroExtPtr(size), m_out.constInt32(logElementSize(typedArrayType))); 8188 if (elementSize(typedArrayType) < 8) { 8189 byteSize = m_out.bitAnd( 8190 m_out.add(byteSize, m_out.constIntPtr(7)), 8191 m_out.constIntPtr(~static_cast<intptr_t>(7))); 8192 } 8193 8194 LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase); 8195 LValue storage = allocateHeapCell(allocator, slowCase); 8196 8197 splatWords( 8198 storage, 8199 m_out.int32Zero, 8200 m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))), 8201 m_out.int64Zero, 8202 m_heaps.typedArrayProperties); 8203 8204 #if CPU(ARM64E) 8205 { 8206 LValue sizePtr = m_out.zeroExtPtr(size); 8207 PatchpointValue* authenticate = m_out.patchpoint(pointerType()); 8208 authenticate->appendSomeRegister(storage); 8209 authenticate->append(sizePtr, B3::ValueRep(B3::ValueRep::SomeLateRegister)); 8210 authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 8211 jit.move(params[1].gpr(), params[0].gpr()); 8212 jit.tagArrayPtr(params[2].gpr(), params[0].gpr()); 8213 }); 8214 storage = authenticate; 8215 } 8216 #endif 8217 8218 ValueFromBlock haveStorage = m_out.anchor(storage); 8219 8220 LValue fastResultValue = nullptr; 8221 switch (typedArrayType) { 8222 #define TYPED_ARRAY_TYPE_CASE(name) \ 8223 case Type ## name: \ 8224 fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \ 8225 break; 8226 FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE) 8227 #undef TYPED_ARRAY_TYPE_CASE 8228 case TypeDataView: 8229 fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase); 8230 break; 8231 default: 8232 RELEASE_ASSERT_NOT_REACHED(); 8233 break; 8234 } 8235 8236 m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector); 8237 m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length); 8238 m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode); 8239 8240 mutatorFence(); 8241 ValueFromBlock fastResult = m_out.anchor(fastResultValue); 8242 m_out.jump(continuation); 8243 8244 m_out.appendTo(slowCase, continuation); 8245 LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage); 8246 8247 VM& vm = this->vm(); 8248 LValue slowResultValue = lazySlowPath( 8249 [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> { 8250 return createLazyCallGenerator(vm, 8251 operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject, 8252 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(), 8253 locations[2].directGPR()); 8254 }, 8255 size, storageValue); 8256 ValueFromBlock slowResult = m_out.anchor(slowResultValue); 8257 m_out.jump(continuation); 8258 8259 m_out.appendTo(continuation, lastNext); 8260 setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); 8240 LValue size = m_out.signExt32To64(lowInt32(m_node->child1())); 8241 8242 emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size); 8243 return; 8244 } 8245 8246 case Int52RepUse: { 8247 RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(typedArrayType)); 8248 8249 LValue size = lowStrictInt52(m_node->child1()); 8250 8251 emitNewTypedArrayWithSize(typedArrayType, globalObject, structure, size); 8261 8252 return; 8262 8253 } … … 8278 8269 } 8279 8270 } 8280 8271 8272 void emitNewTypedArrayWithSize(TypedArrayType typedArrayType, JSGlobalObject* globalObject, RegisteredStructure structure, LValue size64Bits) 8273 { 8274 LBasicBlock smallEnoughCase = m_out.newBlock(); 8275 LBasicBlock slowCase = m_out.newBlock(); 8276 LBasicBlock continuation = m_out.newBlock(); 8277 8278 ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero); 8279 8280 m_out.branch( 8281 m_out.above(size64Bits, m_out.constInt64(JSArrayBufferView::fastSizeLimit)), 8282 rarely(slowCase), usually(smallEnoughCase)); 8283 8284 LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, slowCase); 8285 // We assume through the rest of the fast path that the size is a 32-bit number. 8286 static_assert(isInBounds<int32_t>(JSArrayBufferView::fastSizeLimit)); 8287 8288 LValue byteSize = 8289 m_out.shl(size64Bits, m_out.constInt32(logElementSize(typedArrayType))); 8290 if (elementSize(typedArrayType) < 8) { 8291 byteSize = m_out.bitAnd( 8292 m_out.add(byteSize, m_out.constIntPtr(7)), 8293 m_out.constIntPtr(~static_cast<intptr_t>(7))); 8294 } 8295 8296 LValue allocator = allocatorForSize(vm().primitiveGigacageAuxiliarySpace, byteSize, slowCase); 8297 LValue storage = allocateHeapCell(allocator, slowCase); 8298 8299 splatWords( 8300 storage, 8301 m_out.int32Zero, 8302 m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))), 8303 m_out.int64Zero, 8304 m_heaps.typedArrayProperties); 8305 8306 #if CPU(ARM64E) 8307 { 8308 PatchpointValue* authenticate = m_out.patchpoint(pointerType()); 8309 authenticate->appendSomeRegister(storage); 8310 authenticate->append(size64Bits, B3::ValueRep(B3::ValueRep::SomeLateRegister)); 8311 authenticate->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 8312 jit.move(params[1].gpr(), params[0].gpr()); 8313 jit.tagArrayPtr(params[2].gpr(), params[0].gpr()); 8314 }); 8315 storage = authenticate; 8316 } 8317 #endif 8318 8319 ValueFromBlock haveStorage = m_out.anchor(storage); 8320 8321 LValue fastResultValue = nullptr; 8322 switch (typedArrayType) { 8323 #define TYPED_ARRAY_TYPE_CASE(name) \ 8324 case Type ## name: \ 8325 fastResultValue = allocateObject<JS##name##Array>(structure, m_out.intPtrZero, slowCase); \ 8326 break; 8327 FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(TYPED_ARRAY_TYPE_CASE) 8328 #undef TYPED_ARRAY_TYPE_CASE 8329 case TypeDataView: 8330 fastResultValue = allocateObject<JSDataView>(structure, m_out.intPtrZero, slowCase); 8331 break; 8332 default: 8333 RELEASE_ASSERT_NOT_REACHED(); 8334 break; 8335 } 8336 8337 m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector); 8338 #if USE(LARGE_TYPED_ARRAYS) 8339 m_out.store64(size64Bits, fastResultValue, m_heaps.JSArrayBufferView_length); 8340 #else 8341 m_out.store32(m_out.castToInt32(size64Bits), fastResultValue, m_heaps.JSArrayBufferView_length); 8342 #endif 8343 m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode); 8344 8345 mutatorFence(); 8346 ValueFromBlock fastResult = m_out.anchor(fastResultValue); 8347 m_out.jump(continuation); 8348 8349 m_out.appendTo(slowCase, continuation); 8350 LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage); 8351 8352 VM& vm = this->vm(); 8353 LValue slowResultValue = lazySlowPath( 8354 [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> { 8355 return createLazyCallGenerator(vm, 8356 operationNewTypedArrayWithSizeForType(typedArrayType), locations[0].directGPR(), globalObject, 8357 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(), 8358 locations[2].directGPR()); 8359 }, 8360 size64Bits, storageValue); 8361 ValueFromBlock slowResult = m_out.anchor(slowResultValue); 8362 m_out.jump(continuation); 8363 8364 m_out.appendTo(continuation, lastNext); 8365 setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); 8366 return; 8367 } 8368 8281 8369 void compileAllocatePropertyStorage() 8282 8370 { … … 14657 14745 } 14658 14746 14747 // base and value are 64-bits, begin and end are 32-bits 14748 // stores value at every 64-bits word between base+begin*8 and base+end*8 14659 14749 void splatWords(LValue base, LValue begin, LValue end, LValue value, const AbstractHeap& heap) 14660 14750 { … … 15592 15682 DataViewData data = m_node->dataViewData(); 15593 15683 15684 #if USE(LARGE_TYPED_ARRAYS) 15685 speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0))); 15686 LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length); 15687 #else 15688 // No need for an explicit comparison of index to 0, the check against length catches that case 15594 15689 LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length)); 15690 #endif 15595 15691 LValue indexToCheck = m_out.zeroExtPtr(index); 15596 15692 if (data.byteSize > 1) … … 15735 15831 DataViewData data = m_node->dataViewData(); 15736 15832 15833 #if USE(LARGE_TYPED_ARRAYS) 15834 speculate(OutOfBounds, noValue(), nullptr, m_out.lessThan(index, m_out.constInt32(0))); 15835 LValue length = m_out.load64NonNegative(dataView, m_heaps.JSArrayBufferView_length); 15836 #else 15837 // No need for an explicit comparison of index to 0, the check against length catches that case 15737 15838 LValue length = m_out.zeroExtPtr(m_out.load32NonNegative(dataView, m_heaps.JSArrayBufferView_length)); 15839 #endif 15738 15840 LValue indexToCheck = m_out.zeroExtPtr(index); 15739 15841 if (data.byteSize > 1) … … 17237 17339 #if CPU(ARM64E) 17238 17340 if (kind == Gigacage::Primitive) { 17341 #if USE(ADDRESS64) 17342 LValue size = m_out.load64(base, m_heaps.JSArrayBufferView_length); 17343 #else 17239 17344 LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length); 17345 #endif 17240 17346 return untagArrayPtr(taggedPtr, size); 17241 17347 } -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r284237 r284330 330 330 LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); } 331 331 LValue load32NonNegative(LValue base, const AbstractHeap& field) { return load32(base, field); } 332 LValue load64NonNegative(LValue base, const AbstractHeap& field) { return load64(base, field); } 332 333 333 334 LValue equal(LValue, LValue); -
trunk/Source/JavaScriptCore/jit/IntrinsicEmitter.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2015-20 16Apple Inc. All rights reserved.2 * Copyright (C) 2015-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 87 87 switch (intrinsic()) { 88 88 case TypedArrayLengthIntrinsic: { 89 #if USE(LARGE_TYPED_ARRAYS) 90 jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); 91 jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR); 92 #else 89 93 jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); 90 94 jit.boxInt32(valueGPR, valueRegs); 95 #endif 91 96 state.succeed(); 92 97 return; … … 95 100 case TypedArrayByteLengthIntrinsic: { 96 101 TypedArrayType type = structure()->classInfo()->typedArrayStorageType; 97 102 #if USE(LARGE_TYPED_ARRAYS) 103 jit.load64(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); 104 if (elementSize(type) > 1) 105 jit.lshift64(TrustedImm32(logElementSize(type)), valueGPR); 106 jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR); 107 #else 98 108 jit.load32(MacroAssembler::Address(state.baseGPR, JSArrayBufferView::offsetOfLength()), valueGPR); 99 100 109 if (elementSize(type) > 1) { 101 // We can use a bitshift here since weTypedArrays cannot have byteLength that overflows an int32.102 jit.lshift32( valueGPR,Imm32(logElementSize(type)), valueGPR);110 // We can use a bitshift here since on ADDRESS32 platforms TypedArrays cannot have byteLength that overflows an int32. 111 jit.lshift32(TrustedImm32(logElementSize(type)), valueGPR); 103 112 } 104 105 113 jit.boxInt32(valueGPR, valueRegs); 114 #endif 106 115 state.succeed(); 107 116 return; … … 134 143 135 144 done.link(&jit); 136 145 146 #if USE(LARGE_TYPED_ARRAYS) 147 jit.boxInt52(valueGPR, valueGPR, state.scratchGPR, state.scratchFPR); 148 #else 137 149 jit.boxInt32(valueGPR, valueRegs); 150 #endif 138 151 state.succeed(); 139 152 return; -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r284237 r284330 938 938 if (baseValue.isObject()) { 939 939 JSObject* object = asObject(baseValue); 940 if (object->canSetIndexQuickly(i, value)) { 941 object->setIndexQuickly(vm, i, value); 940 if (object->trySetIndexQuickly(vm, i, value, arrayProfile)) 942 941 return; 943 }944 942 945 943 if (arrayProfile) … … 2343 2341 } 2344 2342 2345 if (std::optional< int32_t> index = subscript.tryGetAsInt32()) {2346 int32_t i = *index;2343 if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) { 2344 uint32_t i = *index; 2347 2345 if (isJSString(baseValue)) { 2348 if ( i >= 0 &&asString(baseValue)->canGetIndex(i))2346 if (asString(baseValue)->canGetIndex(i)) 2349 2347 RELEASE_AND_RETURN(scope, asString(baseValue)->getIndex(globalObject, i)); 2350 2348 if (arrayProfile) … … 2352 2350 } else if (baseValue.isObject()) { 2353 2351 JSObject* object = asObject(baseValue); 2354 if ( object->canGetIndexQuickly(static_cast<uint32_t>(i)))2355 return object->getIndexQuickly(i);2352 if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile)) 2353 return result; 2356 2354 2357 2355 bool skipMarkingOutOfBounds = false; 2358 2356 2359 if (object->indexingType() == ArrayWithContiguous && i >= 0 && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) { 2357 if (object->indexingType() == ArrayWithContiguous 2358 && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) { 2360 2359 // FIXME: expand this to ArrayStorage, Int32, and maybe Double: 2361 2360 // https://bugs.webkit.org/show_bug.cgi?id=182940 … … 2373 2372 } 2374 2373 2375 if (i >= 0) 2376 RELEASE_AND_RETURN(scope, baseValue.get(globalObject, static_cast<uint32_t>(i))); 2374 RELEASE_AND_RETURN(scope, baseValue.get(globalObject, i)); 2377 2375 } else if (subscript.isNumber() && baseValue.isCell() && arrayProfile) 2378 2376 arrayProfile->setOutOfBounds(); -
trunk/Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h
r284237 r284330 150 150 #endif 151 151 152 #if USE(LARGE_TYPED_ARRAYS) 153 #define OFFLINE_ASM_LARGE_TYPED_ARRAYS 1 154 #else 155 #define OFFLINE_ASM_LARGE_TYPED_ARRAYS 0 156 #endif 157 152 158 #if CPU(ADDRESS64) 153 159 #define OFFLINE_ASM_ADDRESS64 1 -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r284237 r284330 1048 1048 } else if (baseValue.isObject()) { 1049 1049 JSObject* object = asObject(baseValue); 1050 if ( object->canGetIndexQuickly(i))1051 return object->getIndexQuickly(i);1050 if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile)) 1051 return result; 1052 1052 1053 1053 bool skipMarkingOutOfBounds = false; … … 1171 1171 JSValue value = getOperand(callFrame, bytecode.m_value); 1172 1172 bool isStrictMode = bytecode.m_ecmaMode.isStrict(); 1173 auto& metadata = bytecode.metadata(codeBlock); 1173 1174 1174 1175 if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) { … … 1176 1177 if (baseValue.isObject()) { 1177 1178 JSObject* object = asObject(baseValue); 1178 if (object->canSetIndexQuickly(i, value)) 1179 object->setIndexQuickly(vm, i, value); 1180 else 1179 if (!object->trySetIndexQuickly(vm, i, value, &metadata.m_arrayProfile)) 1181 1180 object->methodTable(vm)->putByIndex(object, globalObject, i, value, isStrictMode); 1182 1181 LLINT_END(); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r284237 r284330 216 216 const NumberOfStructureIDEntropyBits = constexpr StructureIDTable::s_numberOfEntropyBits 217 217 const StructureEntropyBitsShift = constexpr StructureIDTable::s_entropyBitsShiftForStructurePointer 218 end 219 220 if LARGE_TYPED_ARRAYS 221 const SmallTypedArrayMaxLength = constexpr ArrayProfile::s_smallTypedArrayMaxLength 218 222 end 219 223 … … 1311 1315 end 1312 1316 1313 macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, slowPath) 1317 # Note that index is already sign-extended to be a register width. 1318 macro getByValTypedArray(base, index, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, slowPath) 1314 1319 # First lets check if we even have a typed array. This lets us do some boilerplate up front. 1315 1320 loadb JSCell::m_type[base], t2 … … 1322 1327 const length = t6 1323 1328 const scratch = t7 1324 loadi JSArrayBufferView::m_length[base], length 1325 biaeq index, length, slowPath 1329 if LARGE_TYPED_ARRAYS 1330 loadq JSArrayBufferView::m_length[base], length 1331 bqaeq index, length, slowPath 1332 else 1333 loadi JSArrayBufferView::m_length[base], length 1334 biaeq index, length, slowPath 1335 end 1326 1336 else 1327 1337 # length and scratch are intentionally undefined on this branch because they are not used on other platforms. 1328 biaeq index, JSArrayBufferView::m_length[base], slowPath 1338 if LARGE_TYPED_ARRAYS 1339 bqaeq index, JSArrayBufferView::m_length[base], slowPath 1340 else 1341 biaeq index, JSArrayBufferView::m_length[base], slowPath 1342 end 1343 end 1344 1345 if LARGE_TYPED_ARRAYS 1346 bqbeq index, SmallTypedArrayMaxLength, .smallTypedArray 1347 setLargeTypedArray() 1348 .smallTypedArray: 1329 1349 end 1330 1350 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r284255 r284330 1623 1623 end 1624 1624 1625 macro setLargeTypedArray() 1626 crash() 1627 end 1628 1625 1629 metadata(t5, t2) 1626 1630 get(m_base, t2) … … 1668 1672 1669 1673 .opGetByValNotIndexedStorage: 1670 getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)1674 getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow) 1671 1675 1672 1676 .opGetByValSlow: -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r284237 r284330 1714 1714 end 1715 1715 1716 macro setLargeTypedArray() 1717 if LARGE_TYPED_ARRAYS 1718 storeb 1, OpGetByVal::Metadata::m_arrayProfile + ArrayProfile::m_mayBeLargeTypedArray[t5] 1719 else 1720 crash() 1721 end 1722 end 1723 1716 1724 metadata(t5, t2) 1717 1725 … … 1724 1732 get(m_property, t3) 1725 1733 loadConstantOrVariableInt32(size, t3, t1, .opGetByValSlow) 1734 # This sign-extension makes the bounds-checking in getByValTypedArray work even on 4GB TypedArray. 1726 1735 sxi2q t1, t1 1727 1736 … … 1764 1773 1765 1774 .opGetByValNotIndexedStorage: 1766 getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, .opGetByValSlow)1775 getByValTypedArray(t0, t1, finishIntGetByVal, finishDoubleGetByVal, setLargeTypedArray, .opGetByValSlow) 1767 1776 1768 1777 .opGetByValSlow: -
trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2009-202 0Apple Inc. All rights reserved.2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 43 43 } 44 44 45 SharedArrayBufferContents::SharedArrayBufferContents(void* data, unsignedsize, ArrayBufferDestructorFunction&& destructor)45 SharedArrayBufferContents::SharedArrayBufferContents(void* data, size_t size, ArrayBufferDestructorFunction&& destructor) 46 46 : m_data(data, size) 47 47 , m_destructor(WTFMove(destructor)) … … 69 69 } 70 70 71 ArrayBufferContents::ArrayBufferContents(void* data, unsignedsizeInBytes, ArrayBufferDestructorFunction&& destructor)71 ArrayBufferContents::ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&& destructor) 72 72 : m_data(data, sizeInBytes) 73 73 , m_sizeInBytes(sizeInBytes) … … 110 110 } 111 111 112 void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy policy) 113 { 114 // Do not allow 31-bit overflow of the total size. 115 if (numElements) { 116 unsigned totalSize = numElements * elementByteSize; 117 if (totalSize / numElements != elementByteSize || totalSize > MAX_ARRAY_BUFFER_SIZE) { 118 reset(); 119 return; 120 } 121 } 122 size_t sizeInBytes = static_cast<size_t>(numElements) * static_cast<size_t>(elementByteSize); 123 size_t allocationSize = sizeInBytes; 112 void ArrayBufferContents::tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy policy) 113 { 114 CheckedSize sizeInBytes = numElements; 115 sizeInBytes *= elementByteSize; 116 if (sizeInBytes.hasOverflowed() || sizeInBytes.value() > MAX_ARRAY_BUFFER_SIZE) { 117 reset(); 118 return; 119 } 120 121 size_t allocationSize = sizeInBytes.value(); 124 122 if (!allocationSize) 125 123 allocationSize = 1; // Make sure malloc actually allocates something, but not too much. We use null to mean that the buffer is detached. 126 124 127 125 void* data = Gigacage::tryMalloc(Gigacage::Primitive, allocationSize); 128 m_data = DataType(data, sizeInBytes );126 m_data = DataType(data, sizeInBytes.value()); 129 127 if (!data) { 130 128 reset(); … … 135 133 memset(data, 0, allocationSize); 136 134 137 m_sizeInBytes = sizeInBytes ;135 m_sizeInBytes = sizeInBytes.value(); 138 136 RELEASE_ASSERT(m_sizeInBytes <= MAX_ARRAY_BUFFER_SIZE); 139 137 m_destructor = ArrayBuffer::primitiveGigacageDestructor(); … … 179 177 } 180 178 181 Ref<ArrayBuffer> ArrayBuffer::create( unsignednumElements, unsigned elementByteSize)179 Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize) 182 180 { 183 181 auto buffer = tryCreate(numElements, elementByteSize); … … 192 190 } 193 191 194 Ref<ArrayBuffer> ArrayBuffer::create(const void* source, unsignedbyteLength)192 Ref<ArrayBuffer> ArrayBuffer::create(const void* source, size_t byteLength) 195 193 { 196 194 auto buffer = tryCreate(source, byteLength); … … 209 207 // - JSGenericTypedArrayView<>::slowDownAndWasteMemory. But in that case, the memory should have already come 210 208 // from the cage. 211 Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsignedbyteLength)209 Ref<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, size_t byteLength) 212 210 { 213 211 ASSERT(!Gigacage::isEnabled() || (Gigacage::contains(data) && Gigacage::contains(static_cast<const uint8_t*>(data) + byteLength - 1))); … … 221 219 // differently. 222 220 // - WebAssembly. Wasm should allocate from the cage. 223 Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, unsignedbyteLength, ArrayBufferDestructorFunction&& destructor)221 Ref<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&& destructor) 224 222 { 225 223 if (data && !Gigacage::isCaged(Gigacage::Primitive, data)) … … 230 228 } 231 229 232 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate( unsignednumElements, unsigned elementByteSize)230 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize) 233 231 { 234 232 return tryCreate(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize); … … 240 238 } 241 239 242 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, unsignedbyteLength)240 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(const void* source, size_t byteLength) 243 241 { 244 242 ArrayBufferContents contents; … … 249 247 } 250 248 251 Ref<ArrayBuffer> ArrayBuffer::createUninitialized( unsignednumElements, unsigned elementByteSize)249 Ref<ArrayBuffer> ArrayBuffer::createUninitialized(size_t numElements, unsigned elementByteSize) 252 250 { 253 251 return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize); 254 252 } 255 253 256 RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized( unsignednumElements, unsigned elementByteSize)254 RefPtr<ArrayBuffer> ArrayBuffer::tryCreateUninitialized(size_t numElements, unsigned elementByteSize) 257 255 { 258 256 return tryCreate(numElements, elementByteSize, ArrayBufferContents::DontInitialize); 259 257 } 260 258 261 Ref<ArrayBuffer> ArrayBuffer::create( unsignednumElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)259 Ref<ArrayBuffer> ArrayBuffer::create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy) 262 260 { 263 261 auto buffer = tryCreate(numElements, elementByteSize, policy); … … 267 265 } 268 266 269 Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, unsigned byteLength) 270 { 271 ASSERT(!byteLength || source); 267 Ref<ArrayBuffer> ArrayBuffer::createInternal(ArrayBufferContents&& contents, const void* source, size_t byteLength) 268 { 272 269 auto buffer = adoptRef(*new ArrayBuffer(WTFMove(contents))); 273 memcpy(buffer->data(), source, byteLength); 270 if (byteLength) { 271 ASSERT(source); 272 memcpy(buffer->data(), source, byteLength); 273 } 274 274 return buffer; 275 275 } 276 276 277 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate( unsignednumElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)277 RefPtr<ArrayBuffer> ArrayBuffer::tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy) 278 278 { 279 279 ArrayBufferContents contents; … … 292 292 } 293 293 294 unsigned ArrayBuffer::clampValue(double x, unsigned left, unsignedright)294 size_t ArrayBuffer::clampValue(double x, size_t left, size_t right) 295 295 { 296 296 ASSERT(left <= right); … … 302 302 } 303 303 304 unsignedArrayBuffer::clampIndex(double index) const305 { 306 unsignedcurrentLength = byteLength();304 size_t ArrayBuffer::clampIndex(double index) const 305 { 306 size_t currentLength = byteLength(); 307 307 if (index < 0) 308 308 index = currentLength + index; … … 320 320 } 321 321 322 RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex( unsigned begin, unsignedend) const323 { 324 unsignedsize = begin <= end ? end - begin : 0;322 RefPtr<ArrayBuffer> ArrayBuffer::sliceWithClampedIndex(size_t begin, size_t end) const 323 { 324 size_t size = begin <= end ? end - begin : 0; 325 325 auto result = ArrayBuffer::tryCreate(static_cast<const char*>(data()) + begin, size); 326 326 if (result) -
trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2009-20 18Apple Inc. All rights reserved.2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 #include <wtf/PackedRefPtr.h> 35 35 #include <wtf/SharedTask.h> 36 #include <wtf/StdIntExtras.h> 36 37 #include <wtf/StdLibExtras.h> 37 38 #include <wtf/ThreadSafeRefCounted.h> … … 40 41 namespace JSC { 41 42 43 #if USE(LARGE_TYPED_ARRAYS) 44 static_assert(sizeof(size_t) == sizeof(uint64_t)); 45 #define MAX_ARRAY_BUFFER_SIZE (1ull << 32) 46 #else 47 static_assert(sizeof(size_t) == sizeof(uint32_t)); 48 // Because we are using a size_t to store the size in bytes of array buffers, we cannot support 4GB on 32-bit platforms. 49 // So we are sticking with 2GB. It should in theory be possible to support up to (4GB - 1B) if anyone cares. 42 50 #define MAX_ARRAY_BUFFER_SIZE 0x7fffffffu 51 #endif 43 52 44 53 class VM; … … 52 61 class SharedArrayBufferContents : public ThreadSafeRefCounted<SharedArrayBufferContents> { 53 62 public: 54 SharedArrayBufferContents(void* data, unsigned size, ArrayBufferDestructorFunction&&);63 SharedArrayBufferContents(void* data, size_t, ArrayBufferDestructorFunction&&); 55 64 ~SharedArrayBufferContents(); 56 65 … … 61 70 DataType m_data; 62 71 PackedArrayBufferDestructorFunction m_destructor; 63 unsignedm_sizeInBytes;72 size_t m_sizeInBytes; 64 73 }; 65 74 … … 68 77 public: 69 78 JS_EXPORT_PRIVATE ArrayBufferContents(); 70 JS_EXPORT_PRIVATE ArrayBufferContents(void* data, unsignedsizeInBytes, ArrayBufferDestructorFunction&&);79 JS_EXPORT_PRIVATE ArrayBufferContents(void* data, size_t sizeInBytes, ArrayBufferDestructorFunction&&); 71 80 72 81 JS_EXPORT_PRIVATE ArrayBufferContents(ArrayBufferContents&&); … … 80 89 81 90 void* data() const { return m_data.getMayBeNull(sizeInBytes()); } 82 unsignedsizeInBytes() const { return m_sizeInBytes; }91 size_t sizeInBytes() const { return m_sizeInBytes; } 83 92 84 93 bool isShared() const { return m_shared; } … … 95 104 }; 96 105 97 void tryAllocate( unsignednumElements, unsigned elementByteSize, InitializationPolicy);106 void tryAllocate(size_t numElements, unsigned elementByteSize, InitializationPolicy); 98 107 99 108 void makeShared(); … … 106 115 PackedArrayBufferDestructorFunction m_destructor; 107 116 PackedRefPtr<SharedArrayBufferContents> m_shared; 108 unsignedm_sizeInBytes;117 size_t m_sizeInBytes; 109 118 }; 110 119 111 120 class ArrayBuffer : public GCIncomingRefCounted<ArrayBuffer> { 112 121 public: 113 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create( unsignednumElements, unsigned elementByteSize);122 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize); 114 123 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBuffer&); 115 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, unsignedbyteLength);124 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(const void* source, size_t byteLength); 116 125 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> create(ArrayBufferContents&&); 117 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, unsignedbyteLength);118 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, unsignedbyteLength, ArrayBufferDestructorFunction&&);119 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate( unsignednumElements, unsigned elementByteSize);126 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createAdopted(const void* data, size_t byteLength); 127 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createFromBytes(const void* data, size_t byteLength, ArrayBufferDestructorFunction&&); 128 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize); 120 129 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(ArrayBuffer&); 121 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, unsignedbyteLength);130 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreate(const void* source, size_t byteLength); 122 131 123 132 // Only for use by Uint8ClampedArray::tryCreateUninitialized and SharedBuffer::tryCreateArrayBuffer. 124 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized( unsignednumElements, unsigned elementByteSize);125 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized( unsignednumElements, unsigned elementByteSize);133 JS_EXPORT_PRIVATE static Ref<ArrayBuffer> createUninitialized(size_t numElements, unsigned elementByteSize); 134 JS_EXPORT_PRIVATE static RefPtr<ArrayBuffer> tryCreateUninitialized(size_t numElements, unsigned elementByteSize); 126 135 127 136 inline void* data(); 128 137 inline const void* data() const; 129 inline unsignedbyteLength() const;138 inline size_t byteLength() const; 130 139 131 140 void makeShared(); … … 138 147 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin, double end) const; 139 148 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> slice(double begin) const; 140 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex( unsigned begin, unsignedend) const;149 JS_EXPORT_PRIVATE RefPtr<ArrayBuffer> sliceWithClampedIndex(size_t begin, size_t end) const; 141 150 142 151 inline void pin(); … … 162 171 163 172 private: 164 static Ref<ArrayBuffer> create( unsignednumElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);165 static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, unsigned);166 static RefPtr<ArrayBuffer> tryCreate( unsignednumElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);173 static Ref<ArrayBuffer> create(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); 174 static Ref<ArrayBuffer> createInternal(ArrayBufferContents&&, const void*, size_t); 175 static RefPtr<ArrayBuffer> tryCreate(size_t numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); 167 176 ArrayBuffer(ArrayBufferContents&&); 168 inline unsignedclampIndex(double index) const;169 static inline unsigned clampValue(double x, unsigned left, unsignedright);177 inline size_t clampIndex(double index) const; 178 static inline size_t clampValue(double x, size_t left, size_t right); 170 179 171 180 void notifyDetaching(VM&); … … 193 202 } 194 203 195 unsignedArrayBuffer::byteLength() const204 size_t ArrayBuffer::byteLength() const 196 205 { 197 206 return m_contents.sizeInBytes(); … … 206 215 { 207 216 // FIXME: We probably want to scale this by the shared ref count or something. 208 return sizeof(ArrayBuffer) + static_cast<size_t>(byteLength());217 return sizeof(ArrayBuffer) + byteLength(); 209 218 } 210 219 -
trunk/Source/JavaScriptCore/runtime/ArrayBufferView.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved.2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 26 26 #include "config.h" 27 27 #include "ArrayBufferView.h" 28 #include <wtf/CheckedArithmetic.h>29 28 30 29 namespace JSC { 31 30 32 31 ArrayBufferView::ArrayBufferView( 33 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedbyteLength)32 RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength) 34 33 : m_byteOffset(byteOffset) 35 34 , m_isDetachable(true) … … 37 36 , m_buffer(WTFMove(buffer)) 38 37 { 39 Checked< unsigned, CrashOnOverflow> length(byteOffset);38 Checked<size_t, CrashOnOverflow> length(byteOffset); 40 39 length += byteLength; 41 40 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(length <= m_buffer->byteLength()); -
trunk/Source/JavaScriptCore/runtime/ArrayBufferView.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2009-20 17Apple Inc. All rights reserved.2 * Copyright (C) 2009-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 30 30 #include <algorithm> 31 31 #include <limits.h> 32 #include <wtf/CheckedArithmetic.h> 32 33 #include <wtf/RefCounted.h> 33 34 #include <wtf/RefPtr.h> … … 78 79 void* data() const { return baseAddress(); } 79 80 80 unsignedbyteOffset() const81 size_t byteOffset() const 81 82 { 82 83 if (isDetached()) … … 85 86 } 86 87 87 unsignedbyteLength() const { return m_byteLength; }88 size_t byteLength() const { return m_byteLength; } 88 89 89 90 JS_EXPORT_PRIVATE void setDetachable(bool); … … 93 94 94 95 // Helper to verify byte offset is size aligned. 95 static bool verifyByteOffsetAlignment(unsigned byteOffset, size_t size) 96 { 97 return !(byteOffset & (size - 1)); 98 } 99 100 // Helper to verify that a given sub-range of an ArrayBuffer is 101 // within range. 102 static bool verifySubRangeLength(const ArrayBuffer& buffer, unsigned byteOffset, unsigned numElements, size_t size) 103 { 104 unsigned byteLength = buffer.byteLength(); 96 static bool verifyByteOffsetAlignment(size_t byteOffset, size_t elementSize) 97 { 98 return !(byteOffset & (elementSize - 1)); 99 } 100 101 // Helper to verify that a given sub-range of an ArrayBuffer is within range. 102 static bool verifySubRangeLength(const ArrayBuffer& buffer, size_t byteOffset, size_t numElements, unsigned elementSize) 103 { 104 size_t byteLength = buffer.byteLength(); 105 105 if (byteOffset > byteLength) 106 106 return false; 107 unsigned remainingElements = (byteLength - byteOffset) / size;107 size_t remainingElements = (byteLength - byteOffset) / static_cast<size_t>(elementSize); 108 108 if (numElements > remainingElements) 109 109 return false; … … 114 114 115 115 protected: 116 JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsigned byteLength); 117 118 inline bool setImpl(ArrayBufferView*, unsigned byteOffset); 119 120 inline bool setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset); 121 inline bool getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset); 122 123 inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength); 124 125 static inline void calculateOffsetAndLength( 126 int start, int end, unsigned arraySize, 127 unsigned* offset, unsigned* length); 116 JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength); 117 118 inline bool setImpl(ArrayBufferView*, size_t byteOffset); 119 120 inline bool setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset); 121 inline bool getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset); 122 123 inline bool zeroRangeImpl(size_t byteOffset, size_t rangeByteLength); 128 124 129 125 // Input offset is in number of elements from this array's view; … … 132 128 static void clampOffsetAndNumElements( 133 129 const ArrayBuffer& buffer, 134 unsignedarrayByteOffset,135 unsigned*offset,136 unsigned*numElements)137 { 138 unsigned maxOffset = (UINT_MAX- arrayByteOffset) / sizeof(T);130 size_t arrayByteOffset, 131 size_t *offset, 132 size_t *numElements) 133 { 134 size_t maxOffset = (std::numeric_limits<size_t>::max() - arrayByteOffset) / sizeof(T); 139 135 if (*offset > maxOffset) { 140 136 *offset = buffer.byteLength(); … … 142 138 return; 143 139 } 144 *offset = arrayByteOffset + *offset * sizeof(T); 145 *offset = std::min(buffer.byteLength(), *offset); 146 unsigned remainingElements = (buffer.byteLength() - *offset) / sizeof(T); 140 CheckedSize adjustedOffset = *offset; 141 adjustedOffset *= sizeof(T); 142 adjustedOffset += arrayByteOffset; 143 if (adjustedOffset.hasOverflowed() || adjustedOffset.value() > buffer.byteLength()) 144 *offset = buffer.byteLength(); 145 else 146 *offset = adjustedOffset.value(); 147 size_t remainingElements = (buffer.byteLength() - *offset) / sizeof(T); 147 148 *numElements = std::min(remainingElements, *numElements); 148 149 } 149 150 150 unsigned m_byteOffset : 31; 151 #if USE(LARGE_TYPED_ARRAYS) 152 uint64_t m_byteOffset : 63; 153 #else 154 uint32_t m_byteOffset : 31; 155 #endif 151 156 bool m_isDetachable : 1; 152 unsignedm_byteLength;157 UCPURegister m_byteLength; 153 158 154 159 using BaseAddress = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>; … … 161 166 }; 162 167 163 bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset) 164 { 165 if (byteOffset > byteLength() 166 || byteOffset + array->byteLength() > byteLength() 167 || byteOffset + array->byteLength() < byteOffset) { 168 // Out of range offset or overflow 169 return false; 170 } 171 168 bool ArrayBufferView::setImpl(ArrayBufferView* array, size_t byteOffset) 169 { 170 if (!isSumSmallerThanOrEqual(byteOffset, array->byteLength(), byteLength())) 171 return false; 172 172 173 uint8_t* base = static_cast<uint8_t*>(baseAddress()); 173 174 memmove(base + byteOffset, array->baseAddress(), array->byteLength()); … … 175 176 } 176 177 177 bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, unsigned byteOffset) 178 { 179 if (byteOffset > byteLength() 180 || byteOffset + dataByteLength > byteLength() 181 || byteOffset + dataByteLength < byteOffset) { 182 // Out of range offset or overflow 183 return false; 184 } 178 bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset) 179 { 180 if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength())) 181 return false; 185 182 186 183 uint8_t* base = static_cast<uint8_t*>(baseAddress()); … … 189 186 } 190 187 191 bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, unsigned byteOffset) 192 { 193 if (byteOffset > byteLength() 194 || byteOffset + dataByteLength > byteLength() 195 || byteOffset + dataByteLength < byteOffset) { 196 // Out of range offset or overflow 197 return false; 198 } 188 bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset) 189 { 190 if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength())) 191 return false; 199 192 200 193 const uint8_t* base = static_cast<const uint8_t*>(baseAddress()); … … 203 196 } 204 197 205 bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength) 206 { 207 if (byteOffset > byteLength() 208 || byteOffset + rangeByteLength > byteLength() 209 || byteOffset + rangeByteLength < byteOffset) { 210 // Out of range offset or overflow 211 return false; 212 } 213 198 bool ArrayBufferView::zeroRangeImpl(size_t byteOffset, size_t rangeByteLength) 199 { 200 if (!isSumSmallerThanOrEqual(byteOffset, rangeByteLength, byteLength())) 201 return false; 202 214 203 uint8_t* base = static_cast<uint8_t*>(baseAddress()); 215 204 memset(base + byteOffset, 0, rangeByteLength); … … 217 206 } 218 207 219 void ArrayBufferView::calculateOffsetAndLength(220 int start, int end, unsigned arraySize, unsigned* offset, unsigned* length)221 {222 if (start < 0)223 start += arraySize;224 if (start < 0)225 start = 0;226 if (end < 0)227 end += arraySize;228 if (end < 0)229 end = 0;230 if (static_cast<unsigned>(end) > arraySize)231 end = arraySize;232 if (end < start)233 end = start;234 *offset = static_cast<unsigned>(start);235 *length = static_cast<unsigned>(end - start);236 }237 238 208 } // namespace JSC 239 209 -
trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp
r284237 r284330 121 121 RETURN_IF_EXCEPTION(scope, 0); 122 122 } 123 124 ASSERT(typedArrayView->length() <= static_cast<unsigned>(INT_MAX)); 123 125 124 if (accessIndex >= typedArrayView->length()) { 126 125 throwRangeError(globalObject, scope, "Access index out of bounds for atomic access."_s); -
trunk/Source/JavaScriptCore/runtime/DataView.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2013 , 2016Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 namespace JSC { 34 34 35 DataView::DataView(RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedbyteLength)35 DataView::DataView(RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength) 36 36 : ArrayBufferView(WTFMove(buffer), byteOffset, byteLength) 37 37 { … … 39 39 40 40 Ref<DataView> DataView::create( 41 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedbyteLength)41 RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t byteLength) 42 42 { 43 43 return adoptRef(*new DataView(WTFMove(buffer), byteOffset, byteLength)); … … 46 46 Ref<DataView> DataView::create(RefPtr<ArrayBuffer>&& buffer) 47 47 { 48 unsignedbyteLength = buffer->byteLength();48 size_t byteLength = buffer->byteLength(); 49 49 return create(WTFMove(buffer), 0, byteLength); 50 50 } -
trunk/Source/JavaScriptCore/runtime/DataView.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2013-20 17Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 class DataView final : public ArrayBufferView { 34 34 public: 35 JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedlength);35 JS_EXPORT_PRIVATE static Ref<DataView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length); 36 36 static Ref<DataView> create(RefPtr<ArrayBuffer>&&); 37 37 … … 44 44 45 45 template<typename T> 46 T get( unsignedoffset, bool littleEndian, bool* status = nullptr)46 T get(size_t offset, bool littleEndian, bool* status = nullptr) 47 47 { 48 48 if (status) { … … 60 60 61 61 template<typename T> 62 T read( unsigned& offset, bool littleEndian, bool* status = nullptr)62 T read(size_t& offset, bool littleEndian, bool* status = nullptr) 63 63 { 64 64 T result = this->template get<T>(offset, littleEndian, status); … … 69 69 70 70 template<typename T> 71 void set( unsignedoffset, T value, bool littleEndian, bool* status = nullptr)71 void set(size_t offset, T value, bool littleEndian, bool* status = nullptr) 72 72 { 73 73 if (status) { … … 84 84 85 85 private: 86 DataView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedbyteLength);86 DataView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength); 87 87 }; 88 88 -
trunk/Source/JavaScriptCore/runtime/GenericTypedArrayView.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 class GenericTypedArrayView final : public ArrayBufferView { 35 35 public: 36 static Ref<GenericTypedArrayView> create( unsignedlength);37 static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, unsignedlength);38 static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedlength);39 static RefPtr<GenericTypedArrayView> tryCreate( unsignedlength);40 static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, unsignedlength);41 static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedlength);36 static Ref<GenericTypedArrayView> create(size_t length); 37 static Ref<GenericTypedArrayView> create(const typename Adaptor::Type* array, size_t length); 38 static Ref<GenericTypedArrayView> create(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length); 39 static RefPtr<GenericTypedArrayView> tryCreate(size_t length); 40 static RefPtr<GenericTypedArrayView> tryCreate(const typename Adaptor::Type* array, size_t length); 41 static RefPtr<GenericTypedArrayView> tryCreate(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length); 42 42 43 static Ref<GenericTypedArrayView> createUninitialized( unsignedlength);44 static RefPtr<GenericTypedArrayView> tryCreateUninitialized( unsignedlength);43 static Ref<GenericTypedArrayView> createUninitialized(size_t length); 44 static RefPtr<GenericTypedArrayView> tryCreateUninitialized(size_t length); 45 45 46 46 typename Adaptor::Type* data() const { return static_cast<typename Adaptor::Type*>(baseAddress()); } 47 47 48 bool set(GenericTypedArrayView<Adaptor>* array, unsignedoffset)48 bool set(GenericTypedArrayView<Adaptor>* array, size_t offset) 49 49 { 50 50 return setImpl(array, offset * sizeof(typename Adaptor::Type)); 51 51 } 52 52 53 bool setRange(const typename Adaptor::Type* data, size_t count, unsignedoffset)53 bool setRange(const typename Adaptor::Type* data, size_t count, size_t offset) 54 54 { 55 55 return setRangeImpl( … … 59 59 } 60 60 61 bool zeroRange( unsignedoffset, size_t count)61 bool zeroRange(size_t offset, size_t count) 62 62 { 63 63 return zeroRangeImpl(offset * sizeof(typename Adaptor::Type), count * sizeof(typename Adaptor::Type)); … … 66 66 void zeroFill() { zeroRange(0, length()); } 67 67 68 unsignedlength() const68 size_t length() const 69 69 { 70 70 if (isDetached()) … … 73 73 } 74 74 75 typename Adaptor::Type item( unsignedindex) const75 typename Adaptor::Type item(size_t index) const 76 76 { 77 77 ASSERT_WITH_SECURITY_IMPLICATION(index < this->length()); … … 79 79 } 80 80 81 void set( unsignedindex, double value) const81 void set(size_t index, double value) const 82 82 { 83 83 ASSERT_WITH_SECURITY_IMPLICATION(index < this->length()); … … 85 85 } 86 86 87 void setNative( unsignedindex, typename Adaptor::Type value) const87 void setNative(size_t index, typename Adaptor::Type value) const 88 88 { 89 89 ASSERT_WITH_SECURITY_IMPLICATION(index < this->length()); … … 91 91 } 92 92 93 bool getRange(typename Adaptor::Type* data, size_t count, unsignedoffset)93 bool getRange(typename Adaptor::Type* data, size_t count, size_t offset) 94 94 { 95 95 return getRangeImpl( … … 99 99 } 100 100 101 bool checkInboundData( unsignedoffset, size_t count) const101 bool checkInboundData(size_t offset, size_t count) const 102 102 { 103 unsigned length = this->length(); 104 return (offset <= length 105 && offset + count <= length 106 // check overflow 107 && offset + count >= offset); 103 return isSumSmallerThanOrEqual(offset, count, this->length()); 108 104 } 109 110 RefPtr<GenericTypedArrayView> subarray(int start) const;111 RefPtr<GenericTypedArrayView> subarray(int start, int end) const;112 105 113 106 TypedArrayType getType() const final … … 119 112 120 113 private: 121 GenericTypedArrayView(RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedlength);114 GenericTypedArrayView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length); 122 115 }; 123 116 -
trunk/Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2013 , 2016Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 33 33 template<typename Adaptor> 34 34 GenericTypedArrayView<Adaptor>::GenericTypedArrayView( 35 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedlength)35 RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length) 36 36 : ArrayBufferView(WTFMove(buffer), byteOffset, length * sizeof(typename Adaptor::Type)) 37 37 { 38 ASSERT((length / sizeof(typename Adaptor::Type)) < std::numeric_limits<size_t>::max()); 38 39 } 39 40 40 41 template<typename Adaptor> 41 Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create( unsignedlength)42 Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(size_t length) 42 43 { 43 44 auto result = tryCreate(length); … … 48 49 template<typename Adaptor> 49 50 Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create( 50 const typename Adaptor::Type* array, unsignedlength)51 const typename Adaptor::Type* array, size_t length) 51 52 { 52 53 auto result = tryCreate(array, length); … … 57 58 template<typename Adaptor> 58 59 Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create( 59 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedlength)60 RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length) 60 61 { 61 62 auto result = tryCreate(WTFMove(buffer), byteOffset, length); … … 65 66 66 67 template<typename Adaptor> 67 RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate( unsignedlength)68 RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(size_t length) 68 69 { 69 70 auto buffer = ArrayBuffer::tryCreate(length, sizeof(typename Adaptor::Type)); … … 75 76 template<typename Adaptor> 76 77 RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate( 77 const typename Adaptor::Type* array, unsignedlength)78 const typename Adaptor::Type* array, size_t length) 78 79 { 79 80 RefPtr<GenericTypedArrayView> result = tryCreate(length); … … 86 87 template<typename Adaptor> 87 88 RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate( 88 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsignedlength)89 RefPtr<ArrayBuffer>&& buffer, size_t byteOffset, size_t length) 89 90 { 90 91 if (!buffer) … … 101 102 template<typename Adaptor> 102 103 Ref<GenericTypedArrayView<Adaptor>> 103 GenericTypedArrayView<Adaptor>::createUninitialized( unsignedlength)104 GenericTypedArrayView<Adaptor>::createUninitialized(size_t length) 104 105 { 105 106 auto result = tryCreateUninitialized(length); … … 110 111 template<typename Adaptor> 111 112 RefPtr<GenericTypedArrayView<Adaptor>> 112 GenericTypedArrayView<Adaptor>::tryCreateUninitialized( unsignedlength)113 GenericTypedArrayView<Adaptor>::tryCreateUninitialized(size_t length) 113 114 { 114 115 RefPtr<ArrayBuffer> buffer = … … 117 118 return nullptr; 118 119 return tryCreate(WTFMove(buffer), 0, length); 119 }120 121 template<typename Adaptor>122 RefPtr<GenericTypedArrayView<Adaptor>>123 GenericTypedArrayView<Adaptor>::subarray(int start) const124 {125 return subarray(start, length());126 }127 128 template<typename Adaptor>129 RefPtr<GenericTypedArrayView<Adaptor>>130 GenericTypedArrayView<Adaptor>::subarray(int start, int end) const131 {132 unsigned offset, length;133 calculateOffsetAndLength(start, end, this->length(), &offset, &length);134 ArrayBuffer* buffer = possiblySharedBuffer();135 ASSERT(buffer);136 clampOffsetAndNumElements<Adaptor::Type>(*buffer, byteOffset(), &offset, &length);137 return tryCreate(buffer, offset, length);138 120 } 139 121 -
trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp
r284237 r284330 42 42 43 43 JSArrayBufferView::ConstructionContext::ConstructionContext( 44 Structure* structure, uint32_t length, void* vector)44 Structure* structure, size_t length, void* vector) 45 45 : m_structure(structure) 46 46 , m_vector(vector, length) … … 55 55 56 56 JSArrayBufferView::ConstructionContext::ConstructionContext( 57 VM& vm, Structure* structure, uint32_t length, uint32_telementSize,57 VM& vm, Structure* structure, size_t length, unsigned elementSize, 58 58 InitializationMode mode) 59 59 : m_structure(nullptr) … … 82 82 } 83 83 84 // Don't allow a typed array to use more than 2GB.85 if (length > static_cast<unsigned>(INT_MAX) / elementSize)86 return;87 88 size_t size = static_cast<size_t>(length) * static_cast<size_t>(elementSize); 89 m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size ), length);84 CheckedSize size = length; 85 size *= elementSize; 86 if (size.hasOverflowed() || size > MAX_ARRAY_BUFFER_SIZE) 87 return; 88 89 m_vector = VectorType(Gigacage::tryMalloc(Gigacage::Primitive, size.value()), length); 90 90 if (!m_vector) 91 91 return; … … 93 93 memset(vector(), 0, size); 94 94 95 vm.heap.reportExtraMemoryAllocated(s tatic_cast<size_t>(length) * elementSize);95 vm.heap.reportExtraMemoryAllocated(size.value()); 96 96 97 97 m_structure = structure; … … 101 101 JSArrayBufferView::ConstructionContext::ConstructionContext( 102 102 VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer, 103 unsigned byteOffset, unsignedlength)103 size_t byteOffset, size_t length) 104 104 : m_structure(structure) 105 105 , m_length(length) … … 115 115 JSArrayBufferView::ConstructionContext::ConstructionContext( 116 116 Structure* structure, RefPtr<ArrayBuffer>&& arrayBuffer, 117 unsigned byteOffset, unsignedlength, DataViewTag)117 size_t byteOffset, size_t length, DataViewTag) 118 118 : m_structure(structure) 119 119 , m_length(length) … … 239 239 } 240 240 241 unsigned JSArrayBufferView::byteLength() const 242 { 241 size_t JSArrayBufferView::byteLength() const 242 { 243 #if ASSERT_ENABLED 244 Checked<size_t> result = length(); 245 result *= elementSize(type()); 246 return result.value(); 247 #else 248 // The absence of overflow is already checked in the constructor, so I only add the extra sanity check when asserts are enabled. 243 249 return length() * elementSize(type()); 250 #endif 244 251 } 245 252 … … 268 275 269 276 RefPtr<ArrayBuffer> buffer; 270 unsignedbyteLength = this->byteLength();277 size_t byteLength = this->byteLength(); 271 278 272 279 switch (m_mode) { … … 316 323 if (!buffer) 317 324 return nullptr; 318 unsignedbyteOffset = this->byteOffset();319 unsignedlength = this->length();325 size_t byteOffset = this->byteOffset(); 326 size_t length = this->length(); 320 327 switch (type()) { 321 328 #define FACTORY(type) \ -
trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h
r284237 r284330 109 109 } 110 110 111 static constexpr unsignedfastSizeLimit = 1000;111 static constexpr size_t fastSizeLimit = 1000; 112 112 using VectorPtr = CagedBarrierPtr<Gigacage::Primitive, void, tagCagedPtr>; 113 113 … … 118 118 } 119 119 120 static size_t sizeOf(uint32_t length, uint32_t elementSize) 121 { 122 return (static_cast<size_t>(length) * elementSize + sizeof(EncodedJSValue) - 1) 123 & ~(sizeof(EncodedJSValue) - 1); 120 static size_t sizeOf(size_t length, unsigned elementSize) 121 { 122 Checked<size_t> result = length; 123 result *= elementSize; 124 result += sizeof(EncodedJSValue) - 1; 125 return result.value() & ~(sizeof(EncodedJSValue) - 1); 124 126 } 125 127 … … 137 139 enum InitializationMode { ZeroFill, DontInitialize }; 138 140 139 JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, uint32_t length, uint32_telementSize, InitializationMode = ZeroFill);141 JS_EXPORT_PRIVATE ConstructionContext(VM&, Structure*, size_t length, unsigned elementSize, InitializationMode = ZeroFill); 140 142 141 143 // This is only for constructing fast typed arrays. It's used by the JIT's slow path. 142 ConstructionContext(Structure*, uint32_t length, void* vector);144 ConstructionContext(Structure*, size_t length, void* vector); 143 145 144 146 JS_EXPORT_PRIVATE ConstructionContext( 145 147 VM&, Structure*, RefPtr<ArrayBuffer>&&, 146 unsigned byteOffset, unsignedlength);148 size_t byteOffset, size_t length); 147 149 148 150 enum DataViewTag { DataView }; 149 151 ConstructionContext( 150 152 Structure*, RefPtr<ArrayBuffer>&&, 151 unsigned byteOffset, unsignedlength, DataViewTag);153 size_t byteOffset, size_t length, DataViewTag); 152 154 153 155 bool operator!() const { return !m_structure; } … … 155 157 Structure* structure() const { return m_structure; } 156 158 void* vector() const { return m_vector.getMayBeNull(m_length); } 157 uint32_t length() const { return m_length; }159 size_t length() const { return m_length; } 158 160 TypedArrayMode mode() const { return m_mode; } 159 161 Butterfly* butterfly() const { return m_butterfly; } … … 163 165 using VectorType = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>; 164 166 VectorType m_vector; 165 uint32_t m_length;167 size_t m_length; 166 168 TypedArrayMode m_mode; 167 169 Butterfly* m_butterfly; … … 191 193 void* vectorWithoutPACValidation() const { return m_vector.getUnsafe(); } 192 194 193 inline unsignedbyteOffset();194 inline std::optional< unsigned> byteOffsetConcurrently();195 196 unsignedlength() const { return m_length; }197 unsignedbyteLength() const;195 inline size_t byteOffset(); 196 inline std::optional<size_t> byteOffsetConcurrently(); 197 198 size_t length() const { return m_length; } 199 size_t byteLength() const; 198 200 199 201 DECLARE_EXPORT_INFO; … … 220 222 221 223 VectorPtr m_vector; 222 uint32_t m_length;224 size_t m_length; 223 225 TypedArrayMode m_mode; 224 226 }; -
trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h
r284237 r284330 100 100 bitwise_cast<uint8_t*>(vectorWithoutPACValidation()) - static_cast<uint8_t*>(buffer->data()); 101 101 102 unsigned result = static_cast<unsigned>(delta);102 size_t result = static_cast<size_t>(delta); 103 103 if (requester == Mutator) 104 104 ASSERT(static_cast<ptrdiff_t>(result) == delta); … … 111 111 } 112 112 113 inline unsignedJSArrayBufferView::byteOffset()113 inline size_t JSArrayBufferView::byteOffset() 114 114 { 115 return byteOffsetImpl<Mutator, unsigned>();115 return byteOffsetImpl<Mutator, size_t>(); 116 116 } 117 117 118 inline std::optional< unsigned> JSArrayBufferView::byteOffsetConcurrently()118 inline std::optional<size_t> JSArrayBufferView::byteOffsetConcurrently() 119 119 { 120 return byteOffsetImpl<ConcurrentThread, std::optional< unsigned>>();120 return byteOffsetImpl<ConcurrentThread, std::optional<size_t>>(); 121 121 } 122 122 -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r284237 r284330 38 38 #include <wtf/MediaTime.h> 39 39 #include <wtf/Nonmovable.h> 40 #include <wtf/StdIntExtras.h> 40 41 #include <wtf/StdLibExtras.h> 41 42 #include <wtf/TriState.h> … … 299 300 uint32_t toUInt32(JSGlobalObject*) const; 300 301 uint32_t toIndex(JSGlobalObject*, const char* errorName) const; 302 size_t toTypedArrayIndex(JSGlobalObject*, const char* errorName) const; 301 303 double toLength(JSGlobalObject*) const; 302 304 -
trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
r284237 r284330 70 70 return 0; 71 71 } 72 if (d > std::numeric_limits<unsigned>::max()) { 72 73 if (isInt32()) 74 return asInt32(); 75 76 if (d > static_cast<double>(std::numeric_limits<unsigned>::max())) { 73 77 throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large"))); 74 78 return 0; 75 79 } 76 80 81 RELEASE_AND_RETURN(scope, JSC::toInt32(d)); 82 } 83 84 inline size_t JSValue::toTypedArrayIndex(JSGlobalObject* globalObject, const char* errorName) const 85 { 86 VM& vm = getVM(globalObject); 87 auto scope = DECLARE_THROW_SCOPE(vm); 88 89 double d = toNumber(globalObject); 90 RETURN_IF_EXCEPTION(scope, 0); 91 if (d <= -1) { 92 throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " cannot be negative"))); 93 return 0; 94 } 95 77 96 if (isInt32()) 78 97 return asInt32(); 79 RELEASE_AND_RETURN(scope, JSC::toInt32(d)); 98 99 if (d > static_cast<double>(MAX_ARRAY_BUFFER_SIZE)) { 100 throwException(globalObject, scope, createRangeError(globalObject, makeString(errorName, " too large"))); 101 return 0; 102 } 103 104 // All of this monstrosity is just to give the correct result on 1<<32. 105 size_t outputOffset = 0; 106 double inputOffset = 0; 107 size_t int32Max = std::numeric_limits<int32_t>::max(); 108 if (d > static_cast<double>(int32Max)) { 109 outputOffset = int32Max; 110 inputOffset = int32Max; 111 } 112 RELEASE_AND_RETURN(scope, outputOffset + static_cast<size_t>(static_cast<uint32_t>(JSC::toInt32(d - inputOffset)))); 80 113 } 81 114 -
trunk/Source/JavaScriptCore/runtime/JSDataView.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2013-20 16Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 43 43 JSDataView* JSDataView::create( 44 44 JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer, 45 unsigned byteOffset, unsignedbyteLength)45 size_t byteOffset, size_t byteLength) 46 46 { 47 47 VM& vm = globalObject->vm(); … … 71 71 } 72 72 73 JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, unsigned)73 JSDataView* JSDataView::createUninitialized(JSGlobalObject*, Structure*, size_t) 74 74 { 75 75 UNREACHABLE_FOR_PLATFORM(); … … 77 77 } 78 78 79 JSDataView* JSDataView::create(JSGlobalObject*, Structure*, unsigned)79 JSDataView* JSDataView::create(JSGlobalObject*, Structure*, size_t) 80 80 { 81 81 UNREACHABLE_FOR_PLATFORM(); … … 83 83 } 84 84 85 bool JSDataView::set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsigned)85 bool JSDataView::set(JSGlobalObject*, size_t, JSObject*, size_t, size_t) 86 86 { 87 87 UNREACHABLE_FOR_PLATFORM(); … … 89 89 } 90 90 91 bool JSDataView::setIndex(JSGlobalObject*, unsigned, JSValue)91 bool JSDataView::setIndex(JSGlobalObject*, size_t, JSValue) 92 92 { 93 93 UNREACHABLE_FOR_PLATFORM(); -
trunk/Source/JavaScriptCore/runtime/JSDataView.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2013-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 47 47 48 48 JS_EXPORT_PRIVATE static JSDataView* create( 49 JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset, 50 unsigned byteLength); 49 JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength); 51 50 52 51 // Dummy methods, which don't actually work; these are just in place to 53 52 // placate some template specialization we do elsewhere. 54 static JSDataView* createUninitialized(JSGlobalObject*, Structure*, unsignedlength);55 static JSDataView* create(JSGlobalObject*, Structure*, unsignedlength);56 bool set(JSGlobalObject*, unsigned, JSObject*, unsigned, unsignedlength);57 bool setIndex(JSGlobalObject*, unsigned, JSValue);53 static JSDataView* createUninitialized(JSGlobalObject*, Structure*, size_t length); 54 static JSDataView* create(JSGlobalObject*, Structure*, size_t length); 55 bool set(JSGlobalObject*, size_t, JSObject*, size_t, size_t length); 56 bool setIndex(JSGlobalObject*, size_t, JSValue); 58 57 59 58 ArrayBuffer* possiblySharedBuffer() const { return m_buffer; } -
trunk/Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp
r284237 r284330 1 1 /* 2 * Copyright (C) 2013-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2013-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 137 137 return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s); 138 138 139 unsignedbyteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");139 size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset"); 140 140 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 141 141 142 142 bool littleEndian = false; 143 unsignedelementSize = sizeof(typename Adaptor::Type);143 size_t elementSize = sizeof(typename Adaptor::Type); 144 144 if (elementSize > 1 && callFrame->argumentCount() >= 2) { 145 145 littleEndian = callFrame->uncheckedArgument(1).toBoolean(globalObject); … … 150 150 return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s); 151 151 152 unsignedbyteLength = dataView->length();152 size_t byteLength = dataView->length(); 153 153 if (elementSize > byteLength || byteOffset > byteLength - elementSize) 154 154 return throwVMRangeError(globalObject, scope, "Out of bounds access"_s); … … 183 183 return throwVMTypeError(globalObject, scope, "Receiver of DataView method must be a DataView"_s); 184 184 185 unsignedbyteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset");185 size_t byteOffset = callFrame->argument(0).toIndex(globalObject, "byteOffset"); 186 186 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 187 187 … … 196 196 197 197 bool littleEndian = false; 198 unsignedelementSize = sizeof(typename Adaptor::Type);198 size_t elementSize = sizeof(typename Adaptor::Type); 199 199 if (elementSize > 1 && callFrame->argumentCount() >= 3) { 200 200 littleEndian = callFrame->uncheckedArgument(2).toBoolean(globalObject); … … 205 205 return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s); 206 206 207 unsignedbyteLength = dataView->length();207 size_t byteLength = dataView->length(); 208 208 if (elementSize > byteLength || byteOffset > byteLength - elementSize) 209 209 return throwVMRangeError(globalObject, scope, "Out of bounds access"_s); -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h
r284237 r284330 29 29 #include "ThrowScope.h" 30 30 #include "ToNativeFromValue.h" 31 #include <wtf/CheckedArithmetic.h> 31 32 32 33 namespace JSC { … … 56 57 // Butterfly* B // from JSObject 57 58 // ElementType* V 58 // uint32_t L59 // size_t L 59 60 // TypedArrayMode M 60 61 // 61 // These fields take up a total of f ourpointer-width words. FIXME: Make62 // These fields take up a total of five pointer-width words. FIXME: Make 62 63 // it take less words! 63 64 // … … 104 105 static constexpr unsigned elementSize = sizeof(typename Adaptor::Type); 105 106 106 static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, unsignedlength);107 static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, unsignedlength, void* vector);108 static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, unsignedlength);109 static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, unsigned byteOffset, unsignedlength);107 static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, size_t length); 108 static JSGenericTypedArrayView* createWithFastVector(JSGlobalObject*, Structure*, size_t length, void* vector); 109 static JSGenericTypedArrayView* createUninitialized(JSGlobalObject*, Structure*, size_t length); 110 static JSGenericTypedArrayView* create(JSGlobalObject*, Structure*, RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t length); 110 111 static JSGenericTypedArrayView* create(VM&, Structure*, RefPtr<typename Adaptor::ViewType>&& impl); 111 112 static JSGenericTypedArrayView* create(Structure*, JSGlobalObject*, RefPtr<typename Adaptor::ViewType>&& impl); 112 113 113 unsignedbyteLength() const { return m_length * sizeof(typename Adaptor::Type); }114 size_t byteLength() const { return m_length * sizeof(typename Adaptor::Type); } 114 115 size_t byteSize() const { return sizeOf(m_length, sizeof(typename Adaptor::Type)); } 115 116 … … 123 124 } 124 125 125 bool inBounds( unsignedi) const126 bool inBounds(size_t i) const 126 127 { 127 128 return i < m_length; … … 130 131 // These methods are meant to match indexed access methods that JSObject 131 132 // supports - hence the slight redundancy. 132 bool canGetIndexQuickly( unsignedi) const133 bool canGetIndexQuickly(size_t i) const 133 134 { 134 135 return inBounds(i) && Adaptor::canConvertToJSQuickly; 135 136 } 136 bool canSetIndexQuickly( unsignedi, JSValue value) const137 bool canSetIndexQuickly(size_t i, JSValue value) const 137 138 { 138 139 return i < m_length && value.isNumber() && Adaptor::canConvertToJSQuickly; 139 140 } 140 141 141 typename Adaptor::Type getIndexQuicklyAsNativeValue( unsignedi) const142 typename Adaptor::Type getIndexQuicklyAsNativeValue(size_t i) const 142 143 { 143 144 ASSERT(i < m_length); … … 145 146 } 146 147 147 JSValue getIndexQuickly( unsignedi) const148 JSValue getIndexQuickly(size_t i) const 148 149 { 149 150 return Adaptor::toJSValue(nullptr, getIndexQuicklyAsNativeValue(i)); 150 151 } 151 152 152 void setIndexQuicklyToNativeValue( unsignedi, typename Adaptor::Type value)153 void setIndexQuicklyToNativeValue(size_t i, typename Adaptor::Type value) 153 154 { 154 155 ASSERT(i < m_length); … … 156 157 } 157 158 158 void setIndexQuickly( unsignedi, JSValue value)159 void setIndexQuickly(size_t i, JSValue value) 159 160 { 160 161 ASSERT(!value.isObject()); … … 162 163 } 163 164 164 bool setIndex(JSGlobalObject* globalObject, unsignedi, JSValue jsValue)165 bool setIndex(JSGlobalObject* globalObject, size_t i, JSValue jsValue) 165 166 { 166 167 VM& vm = getVM(globalObject); … … 177 178 } 178 179 179 static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) { return toNativeFromValue<Adaptor>(globalObject, jsValue); } 180 181 static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) { return toNativeFromValueWithoutCoercion<Adaptor>(jsValue); } 180 static ElementType toAdaptorNativeFromValue(JSGlobalObject* globalObject, JSValue jsValue) 181 { 182 return toNativeFromValue<Adaptor>(globalObject, jsValue); 183 } 184 185 static std::optional<ElementType> toAdaptorNativeFromValueWithoutCoercion(JSValue jsValue) 186 { 187 return toNativeFromValueWithoutCoercion<Adaptor>(jsValue); 188 } 182 189 183 190 void sort() … … 199 206 } 200 207 201 bool canAccessRangeQuickly(unsigned offset, unsigned length) 202 { 203 return offset <= m_length 204 && offset + length <= m_length 205 // check overflow 206 && offset + length >= offset; 208 bool canAccessRangeQuickly(size_t offset, size_t length) 209 { 210 return isSumSmallerThanOrEqual(offset, length, m_length); 207 211 } 208 212 209 213 // Like canSetQuickly, except: if it returns false, it will throw the 210 214 // appropriate exception. 211 bool validateRange(JSGlobalObject*, unsigned offset, unsignedlength);215 bool validateRange(JSGlobalObject*, size_t offset, size_t length); 212 216 213 217 // Returns true if successful, and false on error; if it returns false 214 218 // then it will have thrown an exception. 215 bool set(JSGlobalObject*, unsigned offset, JSObject*, unsigned objectOffset, unsigned length, CopyType type = CopyType::Unobservable);219 bool set(JSGlobalObject*, size_t offset, JSObject*, size_t objectOffset, size_t length, CopyType = CopyType::Unobservable); 216 220 217 221 RefPtr<typename Adaptor::ViewType> possiblySharedTypedImpl(); … … 319 323 template<typename OtherAdaptor> 320 324 bool setWithSpecificType( 321 JSGlobalObject*, unsignedoffset, JSGenericTypedArrayView<OtherAdaptor>*,322 unsigned objectOffset, unsignedlength, CopyType);325 JSGlobalObject*, size_t offset, JSGenericTypedArrayView<OtherAdaptor>*, 326 size_t objectOffset, size_t length, CopyType); 323 327 324 328 // The ECMA 6 spec states that floating point Typed Arrays should have the following ordering: … … 350 354 { 351 355 ElementType* array = typedVector(); 352 for ( unsignedi = 0; i < m_length; i++)356 for (size_t i = 0; i < m_length; i++) 353 357 array[i] = purifyNaN(array[i]); 354 358 } -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
r284237 r284330 144 144 145 145 template<typename ViewClass> 146 inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, unsigned offset, std::optional<unsigned> lengthOpt)146 inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, size_t offset, std::optional<size_t> lengthOpt) 147 147 { 148 148 VM& vm = globalObject->vm(); … … 158 158 } 159 159 160 unsignedlength = 0;160 size_t length = 0; 161 161 if (lengthOpt) 162 162 length = lengthOpt.value(); … … 183 183 184 184 if (JSObject* object = jsDynamicCast<JSObject*>(vm, firstValue)) { 185 unsignedlength;185 size_t length; 186 186 JSArrayBuffer* customBuffer = nullptr; 187 187 … … 251 251 } 252 252 253 unsigned length = firstValue.toIndex(globalObject, "length");253 size_t length = firstValue.toTypedArrayIndex(globalObject, "length"); 254 254 RETURN_IF_EXCEPTION(scope, nullptr); 255 255 RELEASE_AND_RETURN(scope, ViewClass::create(globalObject, structure, length)); … … 276 276 277 277 JSValue firstValue = callFrame->uncheckedArgument(0); 278 unsignedoffset = 0;279 std::optional< unsigned> length = std::nullopt;278 size_t offset = 0; 279 std::optional<size_t> length = std::nullopt; 280 280 if (jsDynamicCast<JSArrayBuffer*>(vm, firstValue) && argCount > 1) { 281 281 offset = callFrame->uncheckedArgument(1).toIndex(globalObject, "byteOffset"); … … 286 286 JSValue lengthValue = callFrame->uncheckedArgument(2); 287 287 if (!lengthValue.isUndefined()) { 288 length = lengthValue.to Index(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length");288 length = lengthValue.toTypedArrayIndex(globalObject, ViewClass::TypedArrayStorageType == TypeDataView ? "byteLength" : "length"); 289 289 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 290 290 } -
trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
r284237 r284330 35 35 #include "TypeError.h" 36 36 #include "TypedArrays.h" 37 #include <wtf/CheckedArithmetic.h> 37 38 #include <wtf/text/StringConcatenateNumbers.h> 38 39 … … 48 49 template<typename Adaptor> 49 50 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create( 50 JSGlobalObject* globalObject, Structure* structure, unsignedlength)51 JSGlobalObject* globalObject, Structure* structure, size_t length) 51 52 { 52 53 VM& vm = globalObject->vm(); … … 66 67 template<typename Adaptor> 67 68 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createWithFastVector( 68 JSGlobalObject* globalObject, Structure* structure, unsignedlength, void* vector)69 JSGlobalObject* globalObject, Structure* structure, size_t length, void* vector) 69 70 { 70 71 VM& vm = globalObject->vm(); … … 79 80 80 81 template<typename Adaptor> 81 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, unsignedlength)82 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::createUninitialized(JSGlobalObject* globalObject, Structure* structure, size_t length) 82 83 { 83 84 VM& vm = globalObject->vm(); … … 100 101 JSGenericTypedArrayView<Adaptor>* JSGenericTypedArrayView<Adaptor>::create( 101 102 JSGlobalObject* globalObject, Structure* structure, RefPtr<ArrayBuffer>&& buffer, 102 unsigned byteOffset, unsignedlength)103 { 104 VM& vm = globalObject->vm(); 105 auto scope = DECLARE_THROW_SCOPE(vm); 106 size_t size = sizeof(typename Adaptor::Type);103 size_t byteOffset, size_t length) 104 { 105 VM& vm = globalObject->vm(); 106 auto scope = DECLARE_THROW_SCOPE(vm); 107 size_t elementSize = sizeof(typename Adaptor::Type); 107 108 ASSERT(buffer); 108 if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, size)) {109 if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, elementSize)) { 109 110 throwException(globalObject, scope, createRangeError(globalObject, "Length out of range of buffer")); 110 111 return nullptr; 111 112 } 112 if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, size)) {113 if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, elementSize)) { 113 114 throwException(globalObject, scope, createRangeError(globalObject, "Byte offset is not aligned")); 114 115 return nullptr; … … 146 147 template<typename Adaptor> 147 148 bool JSGenericTypedArrayView<Adaptor>::validateRange( 148 JSGlobalObject* globalObject, unsigned offset, unsignedlength)149 JSGlobalObject* globalObject, size_t offset, size_t length) 149 150 { 150 151 VM& vm = globalObject->vm(); … … 160 161 template<typename OtherAdaptor> 161 162 bool JSGenericTypedArrayView<Adaptor>::setWithSpecificType( 162 JSGlobalObject* globalObject, unsignedoffset, JSGenericTypedArrayView<OtherAdaptor>* other,163 unsigned otherOffset, unsignedlength, CopyType type)163 JSGlobalObject* globalObject, size_t offset, JSGenericTypedArrayView<OtherAdaptor>* other, 164 size_t otherOffset, size_t length, CopyType type) 164 165 { 165 166 VM& vm = globalObject->vm(); … … 219 220 || (elementSize == otherElementSize && vector() <= other->vector()) 220 221 || type == CopyType::LeftToRight) { 221 for ( unsignedi = 0; i < length; ++i) {222 for (size_t i = 0; i < length; ++i) { 222 223 setIndexQuicklyToNativeValue( 223 224 offset + i, OtherAdaptor::template convertTo<Adaptor>( … … 229 230 // Now we either have (2B) or (3) - so first we try to cover (2B). 230 231 if (elementSize == otherElementSize) { 231 for ( unsignedi = length; i--;) {232 for (size_t i = length; i--;) { 232 233 setIndexQuicklyToNativeValue( 233 234 offset + i, OtherAdaptor::template convertTo<Adaptor>( … … 239 240 // Fail: we need an intermediate transfer buffer (i.e. case (3)). 240 241 Vector<typename Adaptor::Type, 32> transferBuffer(length); 241 for ( unsignedi = length; i--;) {242 for (size_t i = length; i--;) { 242 243 transferBuffer[i] = OtherAdaptor::template convertTo<Adaptor>( 243 244 other->getIndexQuicklyAsNativeValue(i + otherOffset)); 244 245 } 245 for ( unsignedi = length; i--;)246 for (size_t i = length; i--;) 246 247 setIndexQuicklyToNativeValue(offset + i, transferBuffer[i]); 247 248 … … 251 252 template<typename Adaptor> 252 253 bool JSGenericTypedArrayView<Adaptor>::set( 253 JSGlobalObject* globalObject, unsigned offset, JSObject* object, unsigned objectOffset, unsignedlength, CopyType type)254 JSGlobalObject* globalObject, size_t offset, JSObject* object, size_t objectOffset, size_t length, CopyType type) 254 255 { 255 256 VM& vm = globalObject->vm(); … … 258 259 const ClassInfo* ci = object->classInfo(vm); 259 260 if (ci->typedArrayStorageType == Adaptor::typeValue) { 260 // The super fast case: we can just mem cpysince we're the same type.261 // The super fast case: we can just memmove since we're the same type. 261 262 JSGenericTypedArrayView* other = jsCast<JSGenericTypedArrayView*>(object); 262 263 length = std::min(length, other->length()); … … 313 314 return false; 314 315 316 // Verify that we won't ever call object->get() with an index of UINT_MAX or more 317 RELEASE_ASSERT(isSumSmallerThanOrEqual(static_cast<uint64_t>(length), static_cast<uint64_t>(objectOffset), static_cast<uint64_t>(std::numeric_limits<unsigned>::max()))); 315 318 // We could optimize this case. But right now, we don't. 316 for ( unsignedi = 0; i < length; ++i) {317 JSValue value = object->get(globalObject, i + objectOffset);319 for (size_t i = 0; i < length; ++i) { 320 JSValue value = object->get(globalObject, static_cast<unsigned>(i + objectOffset)); 318 321 RETURN_IF_EXCEPTION(scope, false); 319 322 bool success = setIndex(globalObject, offset + i, value); -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r284237 r284330 61 61 } 62 62 63 class ArrayProfile; 63 64 class Exception; 64 65 class GetterSetter; … … 212 213 { 213 214 VM& vm = getVM(globalObject); 214 if (canSetIndexQuickly(propertyName, value)) { 215 setIndexQuickly(vm, propertyName, value); 215 if (trySetIndexQuickly(vm, propertyName, value)) 216 216 return true; 217 }218 217 return methodTable(vm)->putByIndex(this, globalObject, propertyName, value, shouldThrow); 219 218 } … … 290 289 291 290 bool canGetIndexQuicklyForTypedArray(unsigned) const; 292 JSValue getIndexQuicklyForTypedArray(unsigned ) const;291 JSValue getIndexQuicklyForTypedArray(unsigned, ArrayProfile* = nullptr) const; 293 292 294 293 bool canGetIndexQuickly(unsigned i) const … … 346 345 } 347 346 } 348 349 JSValue tryGetIndexQuickly(unsigned i) const 347 348 // Uses the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant 349 JSValue tryGetIndexQuickly(unsigned i, ArrayProfile* arrayProfile = nullptr) const 350 350 { 351 351 const Butterfly* butterfly = this->butterfly(); … … 353 353 case ALL_BLANK_INDEXING_TYPES: 354 354 if (canGetIndexQuicklyForTypedArray(i)) 355 return getIndexQuicklyForTypedArray(i );355 return getIndexQuicklyForTypedArray(i, arrayProfile); 356 356 break; 357 357 case ALL_UNDECIDED_INDEXING_TYPES: … … 412 412 } 413 413 414 bool canSetIndexQuicklyForTypedArray(unsigned, JSValue) const;415 414 void setIndexQuicklyForTypedArray(unsigned, JSValue); 416 417 bool canSetIndexQuickly(unsigned i, JSValue value) 415 void setIndexQuicklyForArrayStorageIndexingType(VM&, unsigned, JSValue); 416 417 // Return true to indicate success 418 // Use the (optional) array profile to set the m_mayBeLargeTypedArray bit when relevant 419 bool trySetIndexQuicklyForTypedArray(unsigned, JSValue, ArrayProfile*); 420 bool trySetIndexQuickly(VM& vm, unsigned i, JSValue v, ArrayProfile* arrayProfile = nullptr) 418 421 { 419 422 Butterfly* butterfly = this->butterfly(); 420 423 switch (indexingMode()) { 421 424 case ALL_BLANK_INDEXING_TYPES: 422 return canSetIndexQuicklyForTypedArray(i, value);425 return trySetIndexQuicklyForTypedArray(i, v, arrayProfile); 423 426 case ALL_UNDECIDED_INDEXING_TYPES: 424 427 return false; 425 case ALL_WRITABLE_INT32_INDEXING_TYPES: 426 case ALL_WRITABLE_DOUBLE_INDEXING_TYPES: 427 case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES: 428 case ALL_WRITABLE_INT32_INDEXING_TYPES: { 429 if (i >= butterfly->vectorLength()) 430 return false; 431 if (!v.isInt32()) { 432 convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v); 433 return true; 434 } 435 FALLTHROUGH; 436 } 437 case ALL_WRITABLE_CONTIGUOUS_INDEXING_TYPES: { 438 if (i >= butterfly->vectorLength()) 439 return false; 440 butterfly->contiguous().at(this, i).setWithoutWriteBarrier(v); 441 if (i >= butterfly->publicLength()) 442 butterfly->setPublicLength(i + 1); 443 vm.heap.writeBarrier(this, v); 444 return true; 445 } 446 case ALL_WRITABLE_DOUBLE_INDEXING_TYPES: { 447 if (i >= butterfly->vectorLength()) 448 return false; 449 if (!v.isNumber()) { 450 convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); 451 return true; 452 } 453 double value = v.asNumber(); 454 if (value != value) { 455 convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v); 456 return true; 457 } 458 butterfly->contiguousDouble().at(this, i) = value; 459 if (i >= butterfly->publicLength()) 460 butterfly->setPublicLength(i + 1); 461 return true; 462 } 428 463 case NonArrayWithArrayStorage: 429 464 case ArrayWithArrayStorage: 430 return i < butterfly->vectorLength(); 465 if (i >= butterfly->vectorLength()) 466 return false; 467 setIndexQuicklyForArrayStorageIndexingType(vm, i, v); 468 return true; 431 469 case NonArrayWithSlowPutArrayStorage: 432 470 case ArrayWithSlowPutArrayStorage: 433 return i < butterfly->arrayStorage()->vectorLength() 434 && !!butterfly->arrayStorage()->m_vector[i]; 471 if (i >= butterfly->arrayStorage()->vectorLength() || !butterfly->arrayStorage()->m_vector[i]) 472 return false; 473 setIndexQuicklyForArrayStorageIndexingType(vm, i, v); 474 return true; 435 475 default: 436 if (isCopyOnWrite(indexingMode())) 437 return false; 438 RELEASE_ASSERT_NOT_REACHED(); 476 RELEASE_ASSERT(isCopyOnWrite(indexingMode())); 439 477 return false; 440 478 } 441 479 } 442 480 443 481 void setIndexQuickly(VM& vm, unsigned i, JSValue v) 444 482 { -
trunk/Source/JavaScriptCore/runtime/JSObjectInlines.h
r284237 r284330 466 466 } 467 467 468 inline bool JSObject::canSetIndexQuicklyForTypedArray(unsigned i, JSValue value) const 469 { 470 switch (type()) { 471 #define CASE_TYPED_ARRAY_TYPE(name) \ 472 case name ## ArrayType :\ 473 return jsCast<const JS ## name ## Array *>(this)->canSetIndexQuickly(i, value); 474 FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE) 475 #undef CASE_TYPED_ARRAY_TYPE 476 default: 477 return false; 478 } 479 } 480 481 inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i) const 482 { 468 inline JSValue JSObject::getIndexQuicklyForTypedArray(unsigned i, ArrayProfile* arrayProfile) const 469 { 470 #if USE(LARGE_TYPED_ARRAYS) 471 if (i > ArrayProfile::s_smallTypedArrayMaxLength && arrayProfile) 472 arrayProfile->setMayBeLargeTypedArray(); 473 #else 474 UNUSED_PARAM(arrayProfile); 475 #endif 476 483 477 switch (type()) { 484 478 #define CASE_TYPED_ARRAY_TYPE(name) \ … … 513 507 } 514 508 } 515 509 510 inline void JSObject::setIndexQuicklyForArrayStorageIndexingType(VM& vm, unsigned i, JSValue v) 511 { 512 ArrayStorage* storage = this->butterfly()->arrayStorage(); 513 WriteBarrier<Unknown>& x = storage->m_vector[i]; 514 JSValue old = x.get(); 515 x.set(vm, this, v); 516 if (!old) { 517 ++storage->m_numValuesInVector; 518 if (i >= storage->length()) 519 storage->setLength(i + 1); 520 } 521 } 522 523 inline bool JSObject::trySetIndexQuicklyForTypedArray(unsigned i, JSValue v, ArrayProfile* arrayProfile) 524 { 525 switch (type()) { 526 #if USE(LARGE_TYPED_ARRAYS) 527 #define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \ 528 if ((i > ArrayProfile::s_smallTypedArrayMaxLength) && arrayProfile)\ 529 arrayProfile->setMayBeLargeTypedArray();\ 530 } while (false) 531 #else 532 #define UPDATE_ARRAY_PROFILE(i, arrayProfile) do { \ 533 UNUSED_PARAM(arrayProfile);\ 534 } while (false) 535 #endif 536 #define CASE_TYPED_ARRAY_TYPE(name) \ 537 case name ## ArrayType : { \ 538 auto* typedArray = jsCast<JS ## name ## Array *>(this);\ 539 if (!typedArray->canSetIndexQuickly(i, v))\ 540 return false;\ 541 typedArray->setIndexQuickly(i, v);\ 542 UPDATE_ARRAY_PROFILE(i, arrayProfile);\ 543 return true;\ 544 } 545 FOR_EACH_TYPED_ARRAY_TYPE_EXCLUDING_DATA_VIEW(CASE_TYPED_ARRAY_TYPE) 546 #undef CASE_TYPED_ARRAY_TYPE 547 #undef UPDATE_ARRAY_PROFILE 548 default: 549 return false; 550 } 551 } 552 516 553 inline void JSObject::validatePutOwnDataProperty(VM& vm, PropertyName propertyName, JSValue value) 517 554 { -
trunk/Source/JavaScriptCore/runtime/Operations.h
r284237 r284330 899 899 if (base->isObject()) { 900 900 JSObject* object = asObject(base); 901 if ( object->canGetIndexQuickly(index))902 return JSValue::encode( object->getIndexQuickly(index));901 if (JSValue result = object->tryGetIndexQuickly(index)) 902 return JSValue::encode(result); 903 903 } 904 904 -
trunk/Source/JavaScriptCore/wasm/WasmPageCount.h
r284237 r284330 27 27 28 28 #if ENABLE(WEBASSEMBLY) 29 30 #include "ArrayBuffer.h" 29 31 30 32 #include <limits.h> … … 97 99 static constexpr uint32_t pageSize = 64 * KB; 98 100 private: 99 static constexpr uint32_t maxPageCount = static_cast<uint32_t>( (1ull << 32) / pageSize);101 static constexpr uint32_t maxPageCount = static_cast<uint32_t>(MAX_ARRAY_BUFFER_SIZE / static_cast<uint64_t>(pageSize)); 100 102 101 103 uint32_t m_pageCount; -
trunk/Source/WTF/ChangeLog
r284326 r284330 1 2021-10-16 Robin Morisset <rmorisset@apple.com> 2 3 Allow WASM to use up to 4GB 4 https://bugs.webkit.org/show_bug.cgi?id=229353 5 rdar://81603447 6 7 Reviewed by Yusuke Suzuki. 8 9 Made some of CheckedArithmetic constexpr, and added isSumSmallerThanOrEqual since it is a commonly used test in ArrayBuffer and easy to get wrong in terms of overflow. 10 11 * wtf/CheckedArithmetic.h: 12 (WTF::isInBounds): 13 (WTF::convertSafely): 14 (WTF::isSumSmallerThanOrEqual): 15 1 16 2021-10-16 Tim Horton <timothy_horton@apple.com> 2 17 -
trunk/Source/WTF/wtf/CheckedArithmetic.h
r284237 r284330 1 1 /* 2 * Copyright (C) 2011-20 19Apple Inc. All rights reserved.2 * Copyright (C) 2011-2021 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 145 145 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; 146 146 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, false> { 147 static bool inBounds(Source value)147 static bool constexpr inBounds(Source value) 148 148 { 149 149 // Same signedness so implicit type conversion will always increase precision to widest type. … … 152 152 }; 153 153 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, true> { 154 static bool inBounds(Source value)154 static bool constexpr inBounds(Source value) 155 155 { 156 156 // Same signedness so implicit type conversion will always increase precision to widest type. … … 160 160 161 161 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false, true> { 162 static bool inBounds(Source value)162 static bool constexpr inBounds(Source value) 163 163 { 164 164 // When converting value to unsigned Source, value will become a big value if value is negative. … … 169 169 170 170 template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true, false> { 171 static bool inBounds(Source value)171 static bool constexpr inBounds(Source value) 172 172 { 173 173 // The unsigned Source type has greater precision than the target so max(Target) -> Source will widen. … … 177 177 178 178 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, false> { 179 static bool inBounds(Source)179 static bool constexpr inBounds(Source) 180 180 { 181 181 // Same sign, greater or same precision. … … 185 185 186 186 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, true> { 187 static bool inBounds(Source)187 static bool constexpr inBounds(Source) 188 188 { 189 189 // Same sign, greater or same precision. … … 193 193 194 194 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true, false> { 195 static bool inBounds(Source value)195 static bool constexpr inBounds(Source value) 196 196 { 197 197 // Target is signed with greater or same precision. If strictly greater, it is always safe. … … 203 203 204 204 template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false, true> { 205 static bool inBounds(Source value)205 static bool constexpr inBounds(Source value) 206 206 { 207 207 // Target is unsigned with greater precision. … … 210 210 }; 211 211 212 template <typename Target, typename Source> static inline bool isInBounds(Source value)212 template <typename Target, typename Source> static inline constexpr bool isInBounds(Source value) 213 213 { 214 214 return BoundsChecker<Target, Source>::inBounds(value); 215 215 } 216 216 217 template <typename Target, typename Source> static inline bool convertSafely(Source input, Target& output)217 template <typename Target, typename Source> static inline constexpr bool convertSafely(Source input, Target& output) 218 218 { 219 219 if (!isInBounds<Target>(input)) … … 997 997 } 998 998 999 template<typename T> bool isSumSmallerThanOrEqual(T a, T b, T bound) 1000 { 1001 Checked<T, RecordOverflow> sum = a; 1002 sum += b; 1003 return !sum.hasOverflowed() && sum.value() <= bound; 1004 } 1005 999 1006 } 1000 1007 … … 1018 1025 using WTF::productOverflows; 1019 1026 using WTF::sumOverflows; 1027 using WTF::isSumSmallerThanOrEqual; -
trunk/Source/WTF/wtf/PlatformUse.h
r284306 r284330 142 142 #endif 143 143 144 // FIXME: this should instead be based on SIZE_MAX == UINT64_MAX 145 // But this requires including <cstdint> and Platform.h is included in all kind of weird places, including non-cpp files 146 // And in practice CPU(ADDRESS64) is equivalent on all platforms we support (verified by static_asserts in ArrayBuffer.h) 147 #if CPU(ADDRESS64) 148 #define USE_LARGE_TYPED_ARRAYS 1 149 #else 150 #define USE_LARGE_TYPED_ARRAYS 0 151 #endif 152 144 153 #if USE(JSVALUE64) 145 154 /* FIXME: Enable BIGINT32 optimization again after we ensure Speedometer2 and JetStream2 regressions are fixed. */ -
trunk/Source/WebCore/ChangeLog
r284327 r284330 1 2021-10-16 Robin Morisset <rmorisset@apple.com> 2 3 Allow WASM to use up to 4GB 4 https://bugs.webkit.org/show_bug.cgi?id=229353 5 rdar://81603447 6 7 Reviewed by Yusuke Suzuki. 8 9 Some parts of WebCore use TypedArrays, and would not build after I made the length() function on typed arrays return UCPURegister instead of uint32_t. 10 Most fixes were trivial, the only exception is SerializedScriptValue.cpp, where I had to increment the version number, as ArrayBuffer (and ArrayBufferViews) now write/read their length in a 64-bit field (and same for the byteOffset of ArrayBufferView). 11 12 I also had to add a test in PixelBuffer.cpp that the size of the ArrayBuffer it will try to allocate is < INT32_MAX. 13 Otherwise, the test LayoutTests/fast/shapes/shape-outside-floats/shape-outside-imagedata-overflow.html which checks that very large images are properly rejected without crashing, would timeout. 14 15 No new tests, as the code is already extensively covered by existing tests, and I implemented no new features. 16 17 * Modules/webaudio/AudioBuffer.cpp: 18 (WebCore::AudioBuffer::copyFromChannel): 19 (WebCore::AudioBuffer::copyToChannel): 20 * Modules/webaudio/RealtimeAnalyser.cpp: 21 (WebCore::RealtimeAnalyser::getByteFrequencyData): 22 (WebCore::RealtimeAnalyser::getFloatTimeDomainData): 23 (WebCore::RealtimeAnalyser::getByteTimeDomainData): 24 * bindings/js/SerializedScriptValue.cpp: 25 (WebCore::CloneSerializer::dumpArrayBufferView): 26 (WebCore::CloneSerializer::dumpImageBitmap): 27 (WebCore::CloneSerializer::dumpIfTerminal): 28 (WebCore::CloneDeserializer::readArrayBufferImpl): 29 (WebCore::CloneDeserializer::readArrayBuffer): 30 (WebCore::CloneDeserializer::readArrayBufferViewImpl): 31 (WebCore::CloneDeserializer::readArrayBufferView): 32 * bindings/js/SerializedScriptValue.h: 33 (WebCore::SerializedScriptValue::encode const): 34 (WebCore::SerializedScriptValue::decode): 35 * fileapi/NetworkSendQueue.cpp: 36 (WebCore::NetworkSendQueue::enqueue): 37 * platform/graphics/PixelBuffer.cpp: 38 (WebCore::PixelBuffer::tryCreate): 39 * platform/graphics/iso/ISOBox.h: 40 1 41 2021-10-16 Alan Bujtas <zalan@apple.com> 2 42 -
trunk/Source/WebCore/Modules/webaudio/AudioBuffer.cpp
r284237 r284330 199 199 return { }; 200 200 201 unsignedcount = dataLength - bufferOffset;201 size_t count = dataLength - bufferOffset; 202 202 count = std::min(destination.get().length(), count); 203 203 … … 227 227 return { }; 228 228 229 unsignedcount = dataLength - bufferOffset;229 size_t count = dataLength - bufferOffset; 230 230 count = std::min(source.get().length(), count); 231 231 -
trunk/Source/WebCore/Modules/webaudio/RealtimeAnalyser.cpp
r284237 r284330 197 197 198 198 // Convert from linear magnitude to unsigned-byte decibels. 199 unsigned sourceLength = magnitudeBuffer().size(); 200 size_t length = std::min(sourceLength, destinationArray.length()); 199 size_t sourceLength = magnitudeBuffer().size(); 200 size_t destinationLength = destinationArray.length(); 201 size_t length = std::min(sourceLength, destinationLength); 201 202 if (length > 0) { 202 203 const double rangeScaleFactor = m_maxDecibels == m_minDecibels ? 1 : 1 / (m_maxDecibels - m_minDecibels); … … 228 229 ASSERT(isMainThread()); 229 230 230 unsigned fftSize = this->fftSize(); 231 size_t length = std::min(fftSize, destinationArray.length()); 231 size_t destinationLength = destinationArray.length(); 232 size_t fftSize = this->fftSize(); 233 size_t length = std::min(fftSize, destinationLength); 232 234 if (length > 0) { 233 235 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize; … … 252 254 ASSERT(isMainThread()); 253 255 254 unsigned fftSize = this->fftSize(); 255 size_t length = std::min(fftSize, destinationArray.length()); 256 size_t destinationLength = destinationArray.length(); 257 size_t fftSize = this->fftSize(); 258 size_t length = std::min(fftSize, destinationLength); 256 259 if (length > 0) { 257 260 bool isInputBufferGood = m_inputBuffer.size() == InputBufferSize && m_inputBuffer.size() > fftSize; -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp
r284237 r284330 95 95 #include <JavaScriptCore/YarrFlags.h> 96 96 #include <limits> 97 #include <wtf/CheckedArithmetic.h> 97 98 #include <wtf/CompletionHandler.h> 98 99 #include <wtf/MainThread.h> … … 343 344 * Version 8. added support for ImageData's colorSpace attribute. 344 345 * Version 9. added support for ImageBitmap color space. 346 * Version 10. changed the length (and offsets) of ArrayBuffers (and ArrayBufferViews) from 32 to 64 bits 345 347 */ 346 static const unsigned CurrentVersion = 9;348 static const unsigned CurrentVersion = 10; 347 349 static const unsigned TerminatorTag = 0xFFFFFFFF; 348 350 static const unsigned StringPoolTag = 0xFFFFFFFE; … … 400 402 * | MessagePortReferenceTag <value:uint32_t> 401 403 * | ArrayBuffer 402 * | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint 32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)404 * | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint64_t> <byteLength:uint64_t> (ArrayBuffer | ObjectReference) 403 405 * | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}> 404 406 * | DOMPoint … … 464 466 * 465 467 * ArrayBuffer :- 466 * ArrayBufferTag <length:uint 32_t> <contents:byte{length}>468 * ArrayBufferTag <length:uint64_t> <contents:byte{length}> 467 469 * ArrayBufferTransferTag <value:uint32_t> 468 470 * SharedArrayBufferTag <value:uint32_t> … … 911 913 void dumpBigInt32Data(int32_t integer) 912 914 { 913 static_assert(sizeof(uint64_t) == sizeof(unsigned long long));914 915 write(static_cast<uint8_t>(integer < 0)); 915 916 if (!integer) { … … 921 922 if (value < 0) 922 923 value = -value; 923 write(static_cast<u nsigned long long>(value));924 write(static_cast<uint64_t>(value)); 924 925 } 925 926 #endif … … 927 928 void dumpHeapBigIntData(JSBigInt* bigInt) 928 929 { 929 static_assert(sizeof(uint64_t) == sizeof(unsigned long long));930 930 write(static_cast<uint8_t>(bigInt->sign())); 931 931 if constexpr (sizeof(JSBigInt::Digit) == sizeof(uint64_t)) { 932 932 write(static_cast<uint32_t>(bigInt->length())); 933 933 for (unsigned index = 0; index < bigInt->length(); ++index) 934 write(static_cast<u nsigned long long>(bigInt->digit(index)));934 write(static_cast<uint64_t>(bigInt->digit(index))); 935 935 } else { 936 936 ASSERT(sizeof(JSBigInt::Digit) == sizeof(uint32_t)); … … 945 945 else { 946 946 value = (static_cast<uint64_t>(bigInt->digit(index)) << 32) | value; 947 write(static_cast<u nsigned long long>(value));947 write(static_cast<uint64_t>(value)); 948 948 value = 0; 949 949 } 950 950 } 951 951 if (bigInt->length() & 0x1) 952 write(static_cast<u nsigned long long>(value));952 write(static_cast<uint64_t>(value)); 953 953 } 954 954 } … … 999 999 1000 1000 RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj); 1001 write(static_cast<uint32_t>(arrayBufferView->byteOffset())); 1002 write(static_cast<uint32_t>(arrayBufferView->byteLength())); 1001 uint64_t byteOffset = arrayBufferView->byteOffset(); 1002 write(byteOffset); 1003 uint64_t byteLength = arrayBufferView->byteLength(); 1004 write(byteLength); 1003 1005 RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer(); 1004 1006 if (!arrayBuffer) { … … 1132 1134 write(buffer->colorSpace()); 1133 1135 1134 write(static_cast<uint32_t>(arrayBuffer->byteLength())); 1135 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength()); 1136 CheckedUint32 byteLength = arrayBuffer->byteLength(); 1137 if (byteLength.hasOverflowed()) { 1138 code = SerializationReturnCode::ValidationError; 1139 return; 1140 } 1141 write(byteLength); 1142 write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength); 1136 1143 } 1137 1144 … … 1257 1264 write(blob->url().string()); 1258 1265 write(blob->type()); 1259 write(blob->size()); 1266 static_assert(sizeof(uint64_t) == sizeof(decltype(blob->size()))); 1267 uint64_t size = blob->size(); 1268 write(size); 1260 1269 return true; 1261 1270 } … … 1264 1273 write(data->width()); 1265 1274 write(data->height()); 1266 write(data->data().length()); 1267 write(data->data().data(), data->data().length()); 1275 CheckedUint32 dataLength = data->data().length(); 1276 if (dataLength.hasOverflowed()) { 1277 code = SerializationReturnCode::DataCloneError; 1278 return true; 1279 } 1280 write(dataLength); 1281 write(data->data().data(), dataLength); 1268 1282 write(data->colorSpace()); 1269 1283 return true; … … 1312 1326 1313 1327 write(ArrayBufferTag); 1314 write(arrayBuffer->byteLength()); 1315 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength()); 1328 uint64_t byteLength = arrayBuffer->byteLength(); 1329 write(byteLength); 1330 write(static_cast<const uint8_t*>(arrayBuffer->data()), byteLength); 1316 1331 return true; 1317 1332 } … … 1503 1518 } 1504 1519 1505 void write(u nsigned long longi)1520 void write(uint64_t i) 1506 1521 { 1507 1522 writeLittleEndian(m_buffer, i); … … 2392 2407 } 2393 2408 2394 bool read(u nsigned long long& i)2409 bool read(uint64_t& i) 2395 2410 { 2396 2411 return readLittleEndian(i); … … 2556 2571 } 2557 2572 2558 bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer) 2559 { 2560 uint32_t length; 2573 template<typename LengthType> 2574 bool readArrayBufferImpl(RefPtr<ArrayBuffer>& arrayBuffer) 2575 { 2576 LengthType length; 2561 2577 if (!read(length)) 2562 2578 return false; … … 2570 2586 } 2571 2587 2572 bool readArrayBufferView(VM& vm, JSValue& arrayBufferView) 2588 bool readArrayBuffer(RefPtr<ArrayBuffer>& arrayBuffer) 2589 { 2590 if (m_version < 10) 2591 return readArrayBufferImpl<uint32_t>(arrayBuffer); 2592 return readArrayBufferImpl<uint64_t>(arrayBuffer); 2593 } 2594 2595 template <typename LengthType> 2596 bool readArrayBufferViewImpl(VM& vm, JSValue& arrayBufferView) 2573 2597 { 2574 2598 ArrayBufferViewSubtag arrayBufferViewSubtag; 2575 2599 if (!readArrayBufferViewSubtag(arrayBufferViewSubtag)) 2576 2600 return false; 2577 uint32_tbyteOffset;2601 LengthType byteOffset; 2578 2602 if (!read(byteOffset)) 2579 2603 return false; 2580 uint32_tbyteLength;2604 LengthType byteLength; 2581 2605 if (!read(byteLength)) 2582 2606 return false; … … 2588 2612 if (!elementSize) 2589 2613 return false; 2590 unsignedlength = byteLength / elementSize;2614 LengthType length = byteLength / elementSize; 2591 2615 if (length * elementSize != byteLength) 2592 2616 return false; … … 2633 2657 return false; 2634 2658 } 2659 } 2660 2661 bool readArrayBufferView(VM& vm, JSValue& arrayBufferView) 2662 { 2663 if (m_version < 10) 2664 return readArrayBufferViewImpl<uint32_t>(vm, arrayBufferView); 2665 return readArrayBufferViewImpl<uint64_t>(vm, arrayBufferView); 2635 2666 } 2636 2667 … … 3346 3377 RefPtr<ArrayBuffer> arrayBuffer; 3347 3378 3348 if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBuffer (arrayBuffer)) {3379 if (!read(serializationState) || !read(logicalWidth) || !read(logicalHeight) || !read(resolutionScale) || (m_version > 8 && !read(colorSpace)) || !readArrayBufferImpl<uint32_t>(arrayBuffer)) { 3349 3380 fail(); 3350 3381 return JSValue(); … … 3412 3443 static_assert(sizeof(JSBigInt::Digit) == sizeof(uint64_t)); 3413 3444 if (lengthInUint64 == 1) { 3414 static_assert(sizeof(unsigned long long) == sizeof(uint64_t)); 3415 unsigned long long digit64 = 0; 3445 uint64_t digit64 = 0; 3416 3446 if (!read(digit64)) 3417 3447 return JSValue(); … … 3448 3478 } 3449 3479 for (uint32_t index = 0; index < lengthInUint64; ++index) { 3450 static_assert(sizeof(unsigned long long) == sizeof(uint64_t)); 3451 unsigned long long digit64 = 0; 3480 uint64_t digit64 = 0; 3452 3481 if (!read(digit64)) 3453 3482 return JSValue(); … … 3462 3491 } 3463 3492 for (uint32_t index = 0; index < lengthInUint64; ++index) { 3464 static_assert(sizeof(unsigned long long) == sizeof(uint64_t)); 3465 unsigned long long digit64 = 0; 3493 uint64_t digit64 = 0; 3466 3494 if (!read(digit64)) 3467 3495 return JSValue(); … … 3619 3647 if (!readStringData(type)) 3620 3648 return JSValue(); 3621 u nsigned long longsize = 0;3649 uint64_t size = 0; 3622 3650 if (!read(size)) 3623 3651 return JSValue(); -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.h
r284237 r284330 168 168 encoder << static_cast<uint64_t>(m_arrayBufferContentsArray->size()); 169 169 for (const auto &arrayBufferContents : *m_arrayBufferContentsArray) { 170 encoder << arrayBufferContents.sizeInBytes();170 encoder << static_cast<uint64_t>(arrayBufferContents.sizeInBytes()); 171 171 encoder.encodeFixedLengthData(static_cast<const uint8_t*>(arrayBufferContents.data()), arrayBufferContents.sizeInBytes(), 1); 172 172 } … … 200 200 arrayBufferContentsArray = makeUnique<ArrayBufferContentsArray>(); 201 201 while (arrayLength--) { 202 u nsignedbufferSize;202 uint64_t bufferSize; 203 203 if (!decoder.decode(bufferSize)) 204 return nullptr; 205 CheckedSize checkedBufferSize = bufferSize; 206 if (checkedBufferSize.hasOverflowed()) 204 207 return nullptr; 205 208 if (!decoder.template bufferIsLargeEnoughToContain<uint8_t>(bufferSize)) … … 213 216 return nullptr; 214 217 } 215 arrayBufferContentsArray->append({ buffer, bufferSize, ArrayBuffer::primitiveGigacageDestructor() });218 arrayBufferContentsArray->append({ buffer, checkedBufferSize, ArrayBuffer::primitiveGigacageDestructor() }); 216 219 } 217 220 } -
trunk/Source/WebCore/fileapi/NetworkSendQueue.cpp
r284237 r284330 69 69 auto byteLength = blob.size(); 70 70 if (!byteLength) { 71 enqueue(JSC::ArrayBuffer::create(0U, 1), 0, 0); 71 // The cast looks weird, but is required for the overloading resolution to succeed. 72 // Without it, there is an ambiguity where ArrayBuffer::create(const void* source, size_t byteLength) could be called instead. 73 enqueue(JSC::ArrayBuffer::create(static_cast<size_t>(0U), 1), 0, 0); 72 74 return; 73 75 } -
trunk/Source/WebCore/platform/graphics/PixelBuffer.cpp
r284237 r284330 75 75 if (bufferSize.hasOverflowed()) 76 76 return std::nullopt; 77 if (bufferSize > std::numeric_limits<int32_t>::max()) 78 return std::nullopt; 77 79 auto pixelArray = Uint8ClampedArray::tryCreateUninitialized(bufferSize); 78 80 if (!pixelArray) -
trunk/Source/WebCore/platform/graphics/iso/ISOBox.h
r284237 r284330 28 28 #include "FourCC.h" 29 29 #include <wtf/Forward.h> 30 #include <wtf/StdIntExtras.h> 30 31 #include <wtf/TypeCasts.h> 31 32 … … 64 65 { 65 66 bool readStatus = false; 66 T value = view.template read<T>(offset, endianness == LittleEndian, &readStatus); 67 size_t actualOffset = offset; 68 T value = view.template read<T>(actualOffset, endianness == LittleEndian, &readStatus); 69 RELEASE_ASSERT(isInBounds<uint32_t>(actualOffset)); 70 offset = actualOffset; 67 71 if (!readStatus) 68 72 return false;
Note: See TracChangeset
for help on using the changeset viewer.