diff options
Diffstat (limited to 'deps/v8/src/builtins/builtins-typed-array-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-typed-array-gen.cc | 184 |
1 files changed, 95 insertions, 89 deletions
diff --git a/deps/v8/src/builtins/builtins-typed-array-gen.cc b/deps/v8/src/builtins/builtins-typed-array-gen.cc index c7c416d924..99979b0283 100644 --- a/deps/v8/src/builtins/builtins-typed-array-gen.cc +++ b/deps/v8/src/builtins/builtins-typed-array-gen.cc @@ -5,7 +5,6 @@ #include "src/builtins/builtins-typed-array-gen.h" #include "src/builtins/builtins-constructor-gen.h" -#include "src/builtins/builtins-iterator-gen.h" #include "src/builtins/builtins-utils-gen.h" #include "src/builtins/builtins.h" #include "src/builtins/growable-fixed-array-gen.h" @@ -33,12 +32,12 @@ TNode<Map> TypedArrayBuiltinsAssembler::LoadMapForType( TVARIABLE(Map, var_typed_map); TNode<Map> array_map = LoadMap(array); TNode<Int32T> elements_kind = LoadMapElementsKind(array_map); + ReadOnlyRoots roots(isolate()); DispatchTypedArrayByElementsKind( elements_kind, [&](ElementsKind kind, int size, int typed_array_fun_index) { - Handle<Map> map(isolate()->heap()->MapForFixedTypedArray(kind), - isolate()); + Handle<Map> map(roots.MapForFixedTypedArray(kind), isolate()); var_typed_map = HeapConstant(map); }); @@ -65,11 +64,15 @@ TNode<UintPtrT> TypedArrayBuiltinsAssembler::CalculateExternalPointer( // - Set EmbedderFields to 0. void TypedArrayBuiltinsAssembler::SetupTypedArray(TNode<JSTypedArray> holder, TNode<Smi> length, - TNode<Number> byte_offset, - TNode<Number> byte_length) { + TNode<UintPtrT> byte_offset, + TNode<UintPtrT> byte_length) { StoreObjectField(holder, JSTypedArray::kLengthOffset, length); - StoreObjectField(holder, JSArrayBufferView::kByteOffsetOffset, byte_offset); - StoreObjectField(holder, JSArrayBufferView::kByteLengthOffset, byte_length); + StoreObjectFieldNoWriteBarrier(holder, JSArrayBufferView::kByteOffsetOffset, + byte_offset, + MachineType::PointerRepresentation()); + StoreObjectFieldNoWriteBarrier(holder, JSArrayBufferView::kByteLengthOffset, + byte_length, + MachineType::PointerRepresentation()); for (int offset = JSTypedArray::kSize; offset < JSTypedArray::kSizeWithEmbedderFields; offset += kPointerSize) { StoreObjectField(holder, offset, SmiConstant(0)); @@ -114,7 +117,8 @@ TF_BUILTIN(TypedArrayInitializeWithBuffer, TypedArrayBuiltinsAssembler) { // SmiMul returns a heap number in case of Smi overflow. TNode<Number> byte_length = SmiMul(length, element_size); - SetupTypedArray(holder, length, byte_offset, byte_length); + SetupTypedArray(holder, length, ChangeNonnegativeNumberToUintPtr(byte_offset), + ChangeNonnegativeNumberToUintPtr(byte_length)); AttachBuffer(holder, buffer, fixed_typed_map, length, byte_offset); Return(UndefinedConstant()); } @@ -146,8 +150,6 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { // SmiMul returns a heap number in case of Smi overflow. TNode<Number> byte_length = SmiMul(length, element_size); - SetupTypedArray(holder, length, byte_offset, byte_length); - TNode<Map> fixed_typed_map = LoadMapForType(holder); // If target and new_target for the buffer differ, allocate off-heap. @@ -173,7 +175,7 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { Node* native_context = LoadNativeContext(context); Node* map = LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX); - Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); + Node* empty_fixed_array = LoadRoot(RootIndex::kEmptyFixedArray); Node* buffer = Allocate(JSArrayBuffer::kSizeWithEmbedderFields); StoreMapNoWriteBarrier(buffer, map); @@ -189,14 +191,15 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { // - Set all embedder fields to Smi(0). StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldSlot, SmiConstant(0)); - int32_t bitfield_value = (1 << JSArrayBuffer::IsExternal::kShift) | - (1 << JSArrayBuffer::IsNeuterable::kShift); + int32_t bitfield_value = (1 << JSArrayBuffer::IsExternalBit::kShift) | + (1 << JSArrayBuffer::IsNeuterableBit::kShift); StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldOffset, Int32Constant(bitfield_value), MachineRepresentation::kWord32); StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kByteLengthOffset, - byte_length); + SmiToIntPtr(CAST(byte_length)), + MachineType::PointerRepresentation()); StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBackingStoreOffset, SmiConstant(0)); for (int i = 0; i < v8::ArrayBuffer::kEmbedderFieldCount; i++) { @@ -305,6 +308,8 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { } BIND(&done); + SetupTypedArray(holder, length, ChangeNonnegativeNumberToUintPtr(byte_offset), + ChangeNonnegativeNumberToUintPtr(byte_length)); Return(UndefinedConstant()); } @@ -399,8 +404,8 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( BIND(&length_undefined); { ThrowIfArrayBufferIsDetached(context, buffer, "Construct"); - Node* buffer_byte_length = - LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset); + TNode<Number> buffer_byte_length = ChangeUintPtrToTagged( + LoadObjectField<UintPtrT>(buffer, JSArrayBuffer::kByteLengthOffset)); Node* remainder = CallBuiltin(Builtins::kModulus, context, buffer_byte_length, element_size); @@ -424,8 +429,8 @@ void TypedArrayBuiltinsAssembler::ConstructByArrayBuffer( new_byte_length.Bind(SmiMul(new_length, element_size)); // Reading the byte length must come after the ToIndex operation, which // could cause the buffer to become detached. - Node* buffer_byte_length = - LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset); + TNode<Number> buffer_byte_length = ChangeUintPtrToTagged( + LoadObjectField<UintPtrT>(buffer, JSArrayBuffer::kByteLengthOffset)); Node* end = CallBuiltin(Builtins::kAdd, context, offset.value(), new_byte_length.value()); @@ -502,7 +507,7 @@ void TypedArrayBuiltinsAssembler::ConstructByTypedArray( Goto(&check_for_sab); BIND(&if_notdetached); - source_length = LoadTypedArrayLength(typed_array); + source_length = LoadJSTypedArrayLength(typed_array); Goto(&check_for_sab); // The spec requires that constructing a typed array using a SAB-backed typed @@ -511,7 +516,7 @@ void TypedArrayBuiltinsAssembler::ConstructByTypedArray( BIND(&check_for_sab); TNode<Uint32T> bitfield = LoadObjectField<Uint32T>(source_buffer, JSArrayBuffer::kBitFieldOffset); - Branch(IsSetWord32<JSArrayBuffer::IsShared>(bitfield), &construct, + Branch(IsSetWord32<JSArrayBuffer::IsSharedBit>(bitfield), &construct, &if_buffernotshared); BIND(&if_buffernotshared); @@ -640,8 +645,9 @@ void TypedArrayBuiltinsAssembler::ConstructByIterable( Label fast_path(this), slow_path(this), done(this); CSA_ASSERT(this, IsCallable(iterator_fn)); - TNode<JSArray> array_like = CAST( - CallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn)); + TNode<JSArray> array_like = + CAST(CallBuiltin(Builtins::kIterableToListMayPreserveHoles, context, + iterable, iterator_fn)); TNode<Object> initial_length = LoadJSArrayLength(array_like); TNode<JSFunction> default_constructor = CAST(LoadContextElement( @@ -674,6 +680,17 @@ TF_BUILTIN(CreateTypedArray, TypedArrayBuiltinsAssembler) { ConstructorBuiltinsAssembler constructor_assembler(this->state()); TNode<JSTypedArray> result = CAST( constructor_assembler.EmitFastNewObject(context, target, new_target)); + // We need to set the byte_offset / byte_length to some sane values + // to keep the heap verifier happy. + // TODO(bmeurer): Fix this initialization to not use EmitFastNewObject, + // which causes the problem, since it puts Undefined into all slots of + // the object even though that doesn't make any sense for these fields. + StoreObjectFieldNoWriteBarrier(result, JSTypedArray::kByteOffsetOffset, + UintPtrConstant(0), + MachineType::PointerRepresentation()); + StoreObjectFieldNoWriteBarrier(result, JSTypedArray::kByteLengthOffset, + UintPtrConstant(0), + MachineType::PointerRepresentation()); TNode<Smi> element_size = SmiTag(GetTypedArrayElementSize(LoadElementsKind(result))); @@ -775,50 +792,58 @@ TF_BUILTIN(TypedArrayConstructor, TypedArrayBuiltinsAssembler) { } } -void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeGetter( - Node* context, Node* receiver, const char* method_name, int object_offset) { - // Check if the {receiver} is actually a JSTypedArray. - ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, method_name); - - // Check if the {receiver}'s JSArrayBuffer was neutered. - Node* receiver_buffer = - LoadObjectField(receiver, JSTypedArray::kBufferOffset); - Label if_receiverisneutered(this, Label::kDeferred); - GotoIf(IsDetachedBuffer(receiver_buffer), &if_receiverisneutered); - Return(LoadObjectField(receiver, object_offset)); - - BIND(&if_receiverisneutered); - { - // The {receiver}s buffer was neutered, default to zero. - Return(SmiConstant(0)); - } -} - // ES6 #sec-get-%typedarray%.prototype.bytelength TF_BUILTIN(TypedArrayPrototypeByteLength, TypedArrayBuiltinsAssembler) { + const char* const kMethodName = "get TypedArray.prototype.byteLength"; Node* context = Parameter(Descriptor::kContext); Node* receiver = Parameter(Descriptor::kReceiver); - GenerateTypedArrayPrototypeGetter(context, receiver, - "get TypedArray.prototype.byteLength", - JSTypedArray::kByteLengthOffset); + + // Check if the {receiver} is actually a JSTypedArray. + ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName); + + // Default to zero if the {receiver}s buffer was neutered. + TNode<JSArrayBuffer> receiver_buffer = + LoadJSArrayBufferViewBuffer(CAST(receiver)); + TNode<UintPtrT> byte_length = Select<UintPtrT>( + IsDetachedBuffer(receiver_buffer), [=] { return UintPtrConstant(0); }, + [=] { return LoadJSArrayBufferViewByteLength(CAST(receiver)); }); + Return(ChangeUintPtrToTagged(byte_length)); } // ES6 #sec-get-%typedarray%.prototype.byteoffset TF_BUILTIN(TypedArrayPrototypeByteOffset, TypedArrayBuiltinsAssembler) { + const char* const kMethodName = "get TypedArray.prototype.byteOffset"; Node* context = Parameter(Descriptor::kContext); Node* receiver = Parameter(Descriptor::kReceiver); - GenerateTypedArrayPrototypeGetter(context, receiver, - "get TypedArray.prototype.byteOffset", - JSTypedArray::kByteOffsetOffset); + + // Check if the {receiver} is actually a JSTypedArray. + ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName); + + // Default to zero if the {receiver}s buffer was neutered. + TNode<JSArrayBuffer> receiver_buffer = + LoadJSArrayBufferViewBuffer(CAST(receiver)); + TNode<UintPtrT> byte_offset = Select<UintPtrT>( + IsDetachedBuffer(receiver_buffer), [=] { return UintPtrConstant(0); }, + [=] { return LoadJSArrayBufferViewByteOffset(CAST(receiver)); }); + Return(ChangeUintPtrToTagged(byte_offset)); } // ES6 #sec-get-%typedarray%.prototype.length TF_BUILTIN(TypedArrayPrototypeLength, TypedArrayBuiltinsAssembler) { + const char* const kMethodName = "get TypedArray.prototype.length"; Node* context = Parameter(Descriptor::kContext); Node* receiver = Parameter(Descriptor::kReceiver); - GenerateTypedArrayPrototypeGetter(context, receiver, - "get TypedArray.prototype.length", - JSTypedArray::kLengthOffset); + + // Check if the {receiver} is actually a JSTypedArray. + ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName); + + // Default to zero if the {receiver}s buffer was neutered. + TNode<JSArrayBuffer> receiver_buffer = + LoadJSArrayBufferViewBuffer(CAST(receiver)); + TNode<Smi> length = Select<Smi>( + IsDetachedBuffer(receiver_buffer), [=] { return SmiConstant(0); }, + [=] { return LoadJSTypedArrayLength(CAST(receiver)); }); + Return(length); } TNode<Word32T> TypedArrayBuiltinsAssembler::IsUint8ElementsKind( @@ -923,7 +948,7 @@ TNode<JSTypedArray> TypedArrayBuiltinsAssembler::CreateByLength( // If newTypedArray.[[ArrayLength]] < argumentList[0], throw a TypeError // exception. Label if_length_is_not_short(this); - TNode<Smi> new_length = LoadTypedArrayLength(new_typed_array); + TNode<Smi> new_length = LoadJSTypedArrayLength(new_typed_array); GotoIfNot(SmiLessThan(new_length, len), &if_length_is_not_short); ThrowTypeError(context, MessageTemplate::kTypedArrayTooShort); @@ -979,8 +1004,8 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource( // Check for possible range errors. - TNode<IntPtrT> source_length = SmiUntag(LoadTypedArrayLength(source)); - TNode<IntPtrT> target_length = SmiUntag(LoadTypedArrayLength(target)); + TNode<IntPtrT> source_length = SmiUntag(LoadJSTypedArrayLength(source)); + TNode<IntPtrT> target_length = SmiUntag(LoadJSTypedArrayLength(target)); TNode<IntPtrT> required_target_length = IntPtrAdd(source_length, offset); GotoIf(IntPtrGreaterThan(required_target_length, target_length), @@ -1030,7 +1055,7 @@ void TypedArrayBuiltinsAssembler::SetTypedArraySource( IsBigInt64ElementsKind(target_el_kind)), &exception); - TNode<IntPtrT> source_length = SmiUntag(LoadTypedArrayLength(source)); + TNode<IntPtrT> source_length = SmiUntag(LoadJSTypedArrayLength(source)); CallCCopyTypedArrayElementsToTypedArray(source, target, source_length, offset); Goto(&out); @@ -1051,7 +1076,7 @@ void TypedArrayBuiltinsAssembler::SetJSArraySource( IntPtrLessThanOrEqual(offset, IntPtrConstant(Smi::kMaxValue))); TNode<IntPtrT> source_length = SmiUntag(LoadFastJSArrayLength(source)); - TNode<IntPtrT> target_length = SmiUntag(LoadTypedArrayLength(target)); + TNode<IntPtrT> target_length = SmiUntag(LoadJSTypedArrayLength(target)); // Maybe out of bounds? GotoIf(IntPtrGreaterThan(IntPtrAdd(source_length, offset), target_length), @@ -1266,7 +1291,7 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { TNode<JSTypedArray> source = ValidateTypedArray(context, receiver, method_name); - TNode<Smi> source_length = LoadTypedArrayLength(source); + TNode<Smi> source_length = LoadJSTypedArrayLength(source); // Convert start offset argument to integer, and calculate relative offset. TNode<Object> start = args.GetOptionalArgumentValue(0, SmiConstant(0)); @@ -1299,7 +1324,7 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { CSA_ASSERT(this, Word32BinaryNot(IsDetachedBuffer(LoadObjectField( result_array, JSTypedArray::kBufferOffset)))); TNode<JSArrayBuffer> receiver_buffer = - LoadArrayBufferViewBuffer(CAST(receiver)); + LoadJSArrayBufferViewBuffer(CAST(receiver)); ThrowIfArrayBufferIsDetached(context, receiver_buffer, method_name); // result_array could be a different type from source or share the same @@ -1332,24 +1357,16 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { TNode<IntPtrT> count_bytes = IntPtrMul(SmiToIntPtr(count), source_el_size); #ifdef DEBUG - Label done(this), to_intptr_failed(this, Label::kDeferred); - TNode<IntPtrT> target_byte_length = TryToIntptr( - LoadObjectField<Number>(result_array, JSTypedArray::kByteLengthOffset), - &to_intptr_failed); - CSA_ASSERT(this, IntPtrLessThanOrEqual(count_bytes, target_byte_length)); - - TNode<IntPtrT> source_byte_length = TryToIntptr( - LoadObjectField<Number>(source, JSTypedArray::kByteLengthOffset), - &to_intptr_failed); - TNode<IntPtrT> source_size_in_bytes = - IntPtrSub(source_byte_length, source_start_bytes); - CSA_ASSERT(this, IntPtrLessThanOrEqual(count_bytes, source_size_in_bytes)); - Goto(&done); - - BIND(&to_intptr_failed); - Unreachable(); - - BIND(&done); + TNode<UintPtrT> target_byte_length = + LoadJSArrayBufferViewByteLength(result_array); + CSA_ASSERT(this, UintPtrLessThanOrEqual(Unsigned(count_bytes), + target_byte_length)); + TNode<UintPtrT> source_byte_length = + LoadJSArrayBufferViewByteLength(source); + TNode<UintPtrT> source_size_in_bytes = + UintPtrSub(source_byte_length, Unsigned(source_start_bytes)); + CSA_ASSERT(this, UintPtrLessThanOrEqual(Unsigned(count_bytes), + source_size_in_bytes)); #endif // DEBUG CallCMemmove(target_data_ptr, source_start, count_bytes); @@ -1395,7 +1412,7 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) { // 5. Let buffer be O.[[ViewedArrayBuffer]]. TNode<JSArrayBuffer> buffer = GetBuffer(context, source); // 6. Let srcLength be O.[[ArrayLength]]. - TNode<Smi> source_length = LoadTypedArrayLength(source); + TNode<Smi> source_length = LoadJSTypedArrayLength(source); // 7. Let relativeBegin be ? ToInteger(begin). // 8. If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin), @@ -1430,7 +1447,7 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) { // 14. Let srcByteOffset be O.[[ByteOffset]]. TNode<Number> source_byte_offset = - LoadObjectField<Number>(source, JSTypedArray::kByteOffsetOffset); + ChangeUintPtrToTagged(LoadJSArrayBufferViewByteOffset(source)); // 15. Let beginByteOffset be srcByteOffset + beginIndex × elementSize. TNode<Number> offset = SmiMul(var_begin.value(), SmiFromIntPtr(element_size)); @@ -1606,17 +1623,6 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) { "%TypedArray%.of"); } -// This builtin always returns a new JSArray and is thus safe to use even in the -// presence of code that may call back into user-JS. -TF_BUILTIN(IterableToList, TypedArrayBuiltinsAssembler) { - TNode<Context> context = CAST(Parameter(Descriptor::kContext)); - TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable)); - TNode<Object> iterator_fn = CAST(Parameter(Descriptor::kIteratorFn)); - - IteratorBuiltinsAssembler iterator_assembler(state()); - Return(iterator_assembler.IterableToList(context, iterable, iterator_fn)); -} - // ES6 #sec-%typedarray%.from TF_BUILTIN(TypedArrayFrom, TypedArrayBuiltinsAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); @@ -1818,7 +1824,7 @@ TF_BUILTIN(TypedArrayPrototypeFilter, TypedArrayBuiltinsAssembler) { ValidateTypedArray(context, receiver, method_name); // 3. Let len be O.[[ArrayLength]]. - TNode<Smi> length = LoadTypedArrayLength(source); + TNode<Smi> length = LoadJSTypedArrayLength(source); // 4. If IsCallable(callbackfn) is false, throw a TypeError exception. TNode<Object> callbackfn = args.GetOptionalArgumentValue(0); |