Skip to content

Commit 5cfe1a6

Browse files
bmeurerCommit Bot
authored andcommitted
[es2015] Change JSArrayBufferView::byte_length/byte_offset to uintptr_t.
This is the next step to support large array buffers. On 64-bit archs the full safe integer range is available (up to 2^53-1 bytes in theory). On 32-bit platforms the full Unsigned31 range is allowed, so that we can continue to use CheckBounds for typed arrays and data views in the optimizing compiler (it's generally unlikely that the kernel will give you more than 1GiB of contiguous memory anyways). Drive-by-fix: This introduces proper chokepoints for the byte_offset and byte_length accesses in the CSA code, and also does some renaming for consistency. Bug: v8:4153, v8:7881, v8:8171 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I92a767638532ca9f86084398ce72556c5180cc6e Reviewed-on: https://chromium-review.googlesource.com/1228377 Reviewed-by: Benedikt Meurer <[email protected]> Reviewed-by: Yang Guo <[email protected]> Reviewed-by: Tobias Tebbi <[email protected]> Reviewed-by: Ulan Degenbaev <[email protected]> Commit-Queue: Benedikt Meurer <[email protected]> Cr-Commit-Position: refs/heads/master@{#56008}
1 parent f176c2a commit 5cfe1a6

38 files changed

Lines changed: 345 additions & 318 deletions

src/api.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7567,6 +7567,7 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
75677567
ArrayBufferCreationMode mode) {
75687568
// Embedders must guarantee that the external backing store is valid.
75697569
CHECK(byte_length == 0 || data != nullptr);
7570+
CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength);
75707571
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
75717572
LOG_API(i_isolate, ArrayBuffer, New);
75727573
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
@@ -7598,9 +7599,8 @@ Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
75987599

75997600
size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
76007601
i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
7601-
size_t byte_offset = i::NumberToSize(self->byte_offset());
7602-
size_t bytes_to_copy =
7603-
i::Min(byte_length, i::NumberToSize(self->byte_length()));
7602+
size_t byte_offset = self->byte_offset();
7603+
size_t bytes_to_copy = i::Min(byte_length, self->byte_length());
76047604
if (bytes_to_copy) {
76057605
i::DisallowHeapAllocation no_gc;
76067606
i::Isolate* isolate = self->GetIsolate();
@@ -7631,13 +7631,13 @@ bool v8::ArrayBufferView::HasBuffer() const {
76317631

76327632
size_t v8::ArrayBufferView::ByteOffset() {
76337633
i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7634-
return static_cast<size_t>(obj->byte_offset()->Number());
7634+
return obj->WasNeutered() ? 0 : obj->byte_offset();
76357635
}
76367636

76377637

76387638
size_t v8::ArrayBufferView::ByteLength() {
76397639
i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
7640-
return static_cast<size_t>(obj->byte_length()->Number());
7640+
return obj->WasNeutered() ? 0 : obj->byte_length();
76417641
}
76427642

76437643

src/builtins/base.tq

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,12 @@ extern operator '<' macro IntPtrLessThan(intptr, intptr): bool;
256256
extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bool;
257257
extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bool;
258258
extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bool;
259+
extern operator '>' macro UintPtrGreaterThan(uintptr, uintptr): bool;
259260
extern operator '>=' macro UintPtrGreaterThanOrEqual(uintptr, uintptr): bool;
260261

261262
extern operator '==' macro Float64Equal(float64, float64): bool;
262263
extern operator '!=' macro Float64NotEqual(float64, float64): bool;
264+
extern operator '>' macro Float64GreaterThan(float64, float64): bool;
263265

264266
extern operator
265267
'==' macro BranchIfNumberEqual(Number, Number): never labels Taken, NotTaken;
@@ -287,6 +289,7 @@ extern operator '>>>' macro SmiShr(Smi, constexpr int31): Smi;
287289
extern operator '<<' macro SmiShl(Smi, constexpr int31): Smi;
288290

289291
extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
292+
extern operator '+' macro UintPtrAdd(uintptr, uintptr): uintptr;
290293
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
291294
extern operator '>>>' macro WordShr(uintptr, uintptr): uintptr;
292295
extern operator '<<' macro WordShl(intptr, intptr): intptr;
@@ -312,6 +315,8 @@ extern operator '<<' macro Word32Shl(uint32, uint32): uint32;
312315
extern operator '|' macro Word32Or(int32, int32): int32;
313316
extern operator '|' macro Word32Or(uint32, uint32): uint32;
314317

318+
extern operator '+' macro Float64Add(float64, float64): float64;
319+
315320
extern operator '+' macro NumberAdd(Number, Number): Number;
316321
extern operator '-' macro NumberSub(Number, Number): Number;
317322
extern macro NumberMin(Number, Number): Number;
@@ -396,6 +401,8 @@ Cast<Number>(o: Object): Number labels CastError {
396401
extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
397402
extern macro ChangeInt32ToTagged(int32): Number;
398403
extern macro ChangeUint32ToTagged(uint32): Number;
404+
extern macro ChangeUintPtrToFloat64(uintptr): float64;
405+
extern macro ChangeUintPtrToTagged(uintptr): Number;
399406
extern macro Unsigned(int32): uint32;
400407
extern macro Unsigned(intptr): uintptr;
401408
extern macro Unsigned(RawPtr): uintptr;
@@ -551,6 +558,12 @@ macro Convert<A : type>(d: float64): A;
551558
Convert<Number>(d: float64): Number {
552559
return AllocateHeapNumberWithValue(d);
553560
}
561+
Convert<float64>(ui: uintptr): float64 {
562+
return ChangeUintPtrToFloat64(ui);
563+
}
564+
Convert<Number>(ui: uintptr): Number {
565+
return ChangeUintPtrToTagged(ui);
566+
}
554567
Convert<uintptr>(d: float64): uintptr {
555568
return ChangeFloat64ToUintPtr(d);
556569
}
@@ -659,7 +672,7 @@ extern operator
659672
extern operator '.elements' macro LoadElements(JSObject): FixedArrayBase;
660673
extern operator '.elements=' macro StoreElements(JSObject, FixedArrayBase);
661674

662-
extern operator '.length' macro LoadTypedArrayLength(JSTypedArray): Smi;
675+
extern operator '.length' macro LoadJSTypedArrayLength(JSTypedArray): Smi;
663676
extern operator '.length' macro LoadJSArrayLength(JSArray): Number;
664677
extern operator '.length_fast' macro LoadFastJSArrayLength(JSArray): Smi;
665678
extern operator '.length=' macro StoreJSArrayLength(JSArray, Smi);

src/builtins/builtins-array-gen.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
212212
context(), original_array, length, method_name);
213213
// In the Spec and our current implementation, the length check is already
214214
// performed in TypedArraySpeciesCreate.
215-
CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadTypedArrayLength(a)));
215+
CSA_ASSERT(this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
216216
fast_typed_array_target_ =
217217
Word32Equal(LoadInstanceType(LoadElements(original_array)),
218218
LoadInstanceType(LoadElements(a)));
@@ -530,10 +530,11 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
530530
TNode<JSTypedArray> typed_array = CAST(receiver_);
531531
o_ = typed_array;
532532

533-
TNode<JSArrayBuffer> array_buffer = LoadArrayBufferViewBuffer(typed_array);
533+
TNode<JSArrayBuffer> array_buffer =
534+
LoadJSArrayBufferViewBuffer(typed_array);
534535
ThrowIfArrayBufferIsDetached(context_, array_buffer, name_);
535536

536-
len_ = LoadTypedArrayLength(typed_array);
537+
len_ = LoadJSTypedArrayLength(typed_array);
537538

538539
Label throw_not_callable(this, Label::kDeferred);
539540
Label distinguish_types(this);
@@ -3661,7 +3662,7 @@ TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
36613662
// [[ArrayIteratorNextIndex]] anymore, since a JSTypedArray's
36623663
// length cannot change anymore, so this {iterator} will never
36633664
// produce values again anyways.
3664-
TNode<Smi> length = LoadTypedArrayLength(CAST(array));
3665+
TNode<Smi> length = LoadJSTypedArrayLength(CAST(array));
36653666
GotoIfNot(SmiBelow(CAST(index), length), &allocate_iterator_result);
36663667
StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
36673668
SmiInc(CAST(index)));

src/builtins/builtins-arraybuffer.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ Object* ConstructBuffer(Isolate* isolate, Handle<JSFunction> target,
3535
isolate, result,
3636
JSObject::New(target, new_target, Handle<AllocationSite>::null()));
3737
size_t byte_length;
38-
if (!TryNumberToSize(*length, &byte_length)) {
38+
if (!TryNumberToSize(*length, &byte_length) ||
39+
byte_length > JSArrayBuffer::kMaxByteLength) {
3940
THROW_NEW_ERROR_RETURN_FAILURE(
4041
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4142
}

src/builtins/builtins-data-view-gen.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,17 @@ class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
1717
explicit DataViewBuiltinsAssembler(compiler::CodeAssemblerState* state)
1818
: BaseBuiltinsFromDSLAssembler(state) {}
1919

20-
TNode<Number> LoadDataViewByteOffset(TNode<JSDataView> data_view) {
21-
return CAST(LoadObjectField(data_view, JSDataView::kByteOffsetOffset));
22-
}
23-
24-
TNode<Number> LoadDataViewByteLength(TNode<JSDataView> data_view) {
25-
return CAST(LoadObjectField(data_view, JSDataView::kByteLengthOffset));
26-
}
27-
28-
TNode<Int32T> LoadUint8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset) {
20+
TNode<Int32T> LoadUint8(TNode<RawPtrT> data_pointer, TNode<UintPtrT> offset) {
2921
return UncheckedCast<Int32T>(
3022
Load(MachineType::Uint8(), data_pointer, offset));
3123
}
3224

33-
TNode<Int32T> LoadInt8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset) {
25+
TNode<Int32T> LoadInt8(TNode<RawPtrT> data_pointer, TNode<UintPtrT> offset) {
3426
return UncheckedCast<Int32T>(
3527
Load(MachineType::Int8(), data_pointer, offset));
3628
}
3729

38-
void StoreWord8(TNode<RawPtrT> data_pointer, TNode<IntPtrT> offset,
30+
void StoreWord8(TNode<RawPtrT> data_pointer, TNode<UintPtrT> offset,
3931
TNode<Word32T> value) {
4032
StoreNoWriteBarrier(MachineRepresentation::kWord8, data_pointer, offset,
4133
value);

src/builtins/builtins-dataview.cc

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,43 +43,43 @@ BUILTIN(DataViewConstructor) {
4343
Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
4444

4545
// 4. Let offset be ? ToIndex(byteOffset).
46-
Handle<Object> offset;
4746
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
48-
isolate, offset,
47+
isolate, byte_offset,
4948
Object::ToIndex(isolate, byte_offset, MessageTemplate::kInvalidOffset));
49+
size_t view_byte_offset = byte_offset->Number();
5050

5151
// 5. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
5252
// We currently violate the specification at this point. TODO: Fix that.
5353

5454
// 6. Let bufferByteLength be the value of buffer's
5555
// [[ArrayBufferByteLength]] internal slot.
56-
double const buffer_byte_length = array_buffer->byte_length();
56+
size_t const buffer_byte_length = array_buffer->byte_length();
5757

5858
// 7. If offset > bufferByteLength, throw a RangeError exception.
59-
if (offset->Number() > buffer_byte_length) {
59+
if (view_byte_offset > buffer_byte_length) {
6060
THROW_NEW_ERROR_RETURN_FAILURE(
61-
isolate, NewRangeError(MessageTemplate::kInvalidOffset, offset));
61+
isolate, NewRangeError(MessageTemplate::kInvalidOffset, byte_offset));
6262
}
6363

64-
Handle<Object> view_byte_length;
64+
size_t view_byte_length;
6565
if (byte_length->IsUndefined(isolate)) {
6666
// 8. If byteLength is either not present or undefined, then
6767
// a. Let viewByteLength be bufferByteLength - offset.
68-
view_byte_length =
69-
isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
68+
view_byte_length = buffer_byte_length - view_byte_offset;
7069
} else {
7170
// 9. Else,
7271
// a. Let viewByteLength be ? ToIndex(byteLength).
7372
// b. If offset+viewByteLength > bufferByteLength, throw a
7473
// RangeError exception.
7574
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
76-
isolate, view_byte_length,
75+
isolate, byte_length,
7776
Object::ToIndex(isolate, byte_length,
7877
MessageTemplate::kInvalidDataViewLength));
79-
if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
78+
if (view_byte_offset + byte_length->Number() > buffer_byte_length) {
8079
THROW_NEW_ERROR_RETURN_FAILURE(
8180
isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
8281
}
82+
view_byte_length = byte_length->Number();
8383
}
8484

8585
// 10. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
@@ -97,10 +97,10 @@ BUILTIN(DataViewConstructor) {
9797
Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
9898

9999
// 12. Set O's [[ByteLength]] internal slot to viewByteLength.
100-
Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
100+
Handle<JSDataView>::cast(result)->set_byte_length(view_byte_length);
101101

102102
// 13. Set O's [[ByteOffset]] internal slot to offset.
103-
Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
103+
Handle<JSDataView>::cast(result)->set_byte_offset(view_byte_offset);
104104

105105
// 14. Return O.
106106
return *result;

src/builtins/builtins-sharedarraybuffer-gen.cc

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
5050
&invalid);
5151

5252
// Fail if the array's JSArrayBuffer is not shared.
53-
Node* array_buffer = LoadObjectField(tagged, JSTypedArray::kBufferOffset);
54-
Node* bitfield = LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldOffset,
55-
MachineType::Uint32());
53+
TNode<JSArrayBuffer> array_buffer = LoadJSArrayBufferViewBuffer(CAST(tagged));
54+
TNode<Uint32T> bitfield = LoadJSArrayBufferBitField(array_buffer);
5655
GotoIfNot(IsSetWord32<JSArrayBuffer::IsSharedBit>(bitfield), &invalid);
5756

5857
// Fail if the array's element type is float32, float64 or clamped.
@@ -76,12 +75,9 @@ void SharedArrayBufferBuiltinsAssembler::ValidateSharedTypedArray(
7675
BIND(&not_float_or_clamped);
7776
*out_instance_type = elements_instance_type;
7877

79-
Node* backing_store =
80-
LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
81-
Node* byte_offset = ChangeUint32ToWord(TruncateTaggedToWord32(
82-
context, LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
83-
*out_backing_store =
84-
IntPtrAdd(BitcastTaggedToWord(backing_store), byte_offset);
78+
TNode<RawPtrT> backing_store = LoadJSArrayBufferBackingStore(array_buffer);
79+
TNode<UintPtrT> byte_offset = LoadJSArrayBufferViewByteOffset(CAST(tagged));
80+
*out_backing_store = IntPtrAdd(backing_store, byte_offset);
8581
}
8682

8783
// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
@@ -112,7 +108,7 @@ void SharedArrayBufferBuiltinsAssembler::ValidateAtomicIndex(Node* array,
112108
// Check if the index is in bounds. If not, throw RangeError.
113109
Label check_passed(this);
114110
Node* array_length_word32 =
115-
TruncateTaggedToWord32(context, LoadTypedArrayLength(CAST(array)));
111+
TruncateTaggedToWord32(context, LoadJSTypedArrayLength(CAST(array)));
116112
GotoIf(Uint32LessThan(index_word, array_length_word32), &check_passed);
117113

118114
ThrowRangeError(context, MessageTemplate::kInvalidAtomicAccessIndex);
@@ -130,7 +126,7 @@ void SharedArrayBufferBuiltinsAssembler::DebugSanityCheckAtomicIndex(
130126
CSA_ASSERT(this,
131127
Uint32LessThan(index_word,
132128
TruncateTaggedToWord32(
133-
context, LoadTypedArrayLength(CAST(array)))));
129+
context, LoadJSTypedArrayLength(CAST(array)))));
134130
}
135131
#endif
136132

src/builtins/builtins-sharedarraybuffer.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ BUILTIN(AtomicsWake) {
113113
}
114114

115115
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
116-
size_t addr = (i << 2) + NumberToSize(sta->byte_offset());
116+
size_t addr = (i << 2) + sta->byte_offset();
117117

118118
return FutexEmulation::Wake(array_buffer, addr, c);
119119
}
@@ -158,7 +158,7 @@ BUILTIN(AtomicsWait) {
158158
}
159159

160160
Handle<JSArrayBuffer> array_buffer = sta->GetBuffer();
161-
size_t addr = (i << 2) + NumberToSize(sta->byte_offset());
161+
size_t addr = (i << 2) + sta->byte_offset();
162162

163163
return FutexEmulation::Wait(isolate, array_buffer, addr, value_int32,
164164
timeout_number);

0 commit comments

Comments
 (0)