| Index: src/builtins/builtins-typedarray.cc
|
| diff --git a/src/builtins/builtins-typedarray.cc b/src/builtins/builtins-typedarray.cc
|
| index e4326c92445e0f32b0061041ee188b45c82a38db..43995920bd32b42737e22d129717a056aeb1bab7 100644
|
| --- a/src/builtins/builtins-typedarray.cc
|
| +++ b/src/builtins/builtins-typedarray.cc
|
| @@ -4,7 +4,6 @@
|
|
|
| #include "src/builtins/builtins-utils.h"
|
| #include "src/builtins/builtins.h"
|
| -#include "src/code-stub-assembler.h"
|
| #include "src/counters.h"
|
| #include "src/elements.h"
|
| #include "src/objects-inl.h"
|
| @@ -12,463 +11,9 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
| - public:
|
| - explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
| - : CodeStubAssembler(state) {}
|
| -
|
| - protected:
|
| - void GenerateTypedArrayPrototypeGetter(const char* method_name,
|
| - int object_offset);
|
| - template <IterationKind kIterationKind>
|
| - void GenerateTypedArrayPrototypeIterationMethod(const char* method_name);
|
| -
|
| - void LoadMapAndElementsSize(Node* const array, Variable* typed_map,
|
| - Variable* size);
|
| -
|
| - void CalculateExternalPointer(Node* const backing_store,
|
| - Node* const byte_offset,
|
| - Variable* external_pointer);
|
| - void DoInitialize(Node* const holder, Node* length, Node* const maybe_buffer,
|
| - Node* const byte_offset, Node* byte_length,
|
| - Node* const initialize, Node* const context);
|
| -};
|
| -
|
| -void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* const array,
|
| - Variable* typed_map,
|
| - Variable* size) {
|
| - Label unreachable(this), done(this);
|
| - Label uint8_elements(this), uint8_clamped_elements(this), int8_elements(this),
|
| - uint16_elements(this), int16_elements(this), uint32_elements(this),
|
| - int32_elements(this), float32_elements(this), float64_elements(this);
|
| - Label* elements_kind_labels[] = {
|
| - &uint8_elements, &uint8_clamped_elements, &int8_elements,
|
| - &uint16_elements, &int16_elements, &uint32_elements,
|
| - &int32_elements, &float32_elements, &float64_elements};
|
| - int32_t elements_kinds[] = {
|
| - UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
|
| - UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
|
| - INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS};
|
| - const size_t kTypedElementsKindCount = LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
|
| - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
|
| - 1;
|
| - DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
|
| - DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
|
| -
|
| - Node* array_map = LoadMap(array);
|
| - Node* elements_kind = LoadMapElementsKind(array_map);
|
| - Switch(elements_kind, &unreachable, elements_kinds, elements_kind_labels,
|
| - kTypedElementsKindCount);
|
| -
|
| - for (int i = 0; i < static_cast<int>(kTypedElementsKindCount); i++) {
|
| - Bind(elements_kind_labels[i]);
|
| - {
|
| - ElementsKind kind = static_cast<ElementsKind>(elements_kinds[i]);
|
| - ExternalArrayType type =
|
| - isolate()->factory()->GetArrayTypeFromElementsKind(kind);
|
| - Handle<Map> map(isolate()->heap()->MapForFixedTypedArray(type));
|
| - typed_map->Bind(HeapConstant(map));
|
| - size->Bind(SmiConstant(static_cast<int>(
|
| - isolate()->factory()->GetExternalArrayElementSize(type))));
|
| - Goto(&done);
|
| - }
|
| - }
|
| -
|
| - Bind(&unreachable);
|
| - { Unreachable(); }
|
| - Bind(&done);
|
| -}
|
| -
|
| -// The byte_offset can be higher than Smi range, in which case to perform the
|
| -// pointer arithmetic necessary to calculate external_pointer, converting
|
| -// byte_offset to an intptr is more difficult. The max byte_offset is 8 * MaxSmi
|
| -// on the particular platform. 32 bit platforms are self-limiting, because we
|
| -// can't allocate an array bigger than our 32-bit arithmetic range anyway. 64
|
| -// bit platforms could theoretically have an offset up to 2^35 - 1, so we may
|
| -// need to convert the float heap number to an intptr.
|
| -void TypedArrayBuiltinsAssembler::CalculateExternalPointer(
|
| - Node* const backing_store, Node* const byte_offset,
|
| - Variable* external_pointer) {
|
| - Label offset_is_smi(this), offset_not_smi(this), done(this);
|
| - Branch(TaggedIsSmi(byte_offset), &offset_is_smi, &offset_not_smi);
|
| -
|
| - Bind(&offset_is_smi);
|
| - {
|
| - external_pointer->Bind(IntPtrAdd(backing_store, SmiToWord(byte_offset)));
|
| - Goto(&done);
|
| - }
|
| -
|
| - Bind(&offset_not_smi);
|
| - {
|
| - Node* heap_number = LoadHeapNumberValue(byte_offset);
|
| - Node* intrptr_value = ChangeFloat64ToUintPtr(heap_number);
|
| - external_pointer->Bind(IntPtrAdd(backing_store, intrptr_value));
|
| - Goto(&done);
|
| - }
|
| -
|
| - Bind(&done);
|
| -}
|
| -
|
| -void TypedArrayBuiltinsAssembler::DoInitialize(Node* const holder, Node* length,
|
| - Node* const maybe_buffer,
|
| - Node* const byte_offset,
|
| - Node* byte_length,
|
| - Node* const initialize,
|
| - Node* const context) {
|
| - static const int32_t fta_base_data_offset =
|
| - FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
|
| -
|
| - Label setup_holder(this), alloc_array_buffer(this), aligned(this),
|
| - allocate_elements(this), attach_buffer(this), done(this);
|
| - Variable fixed_typed_map(this, MachineRepresentation::kTagged);
|
| - Variable element_size(this, MachineRepresentation::kTagged);
|
| - Variable total_size(this, MachineType::PointerRepresentation());
|
| -
|
| - // Make sure length is a Smi. The caller guarantees this is the case.
|
| - length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
|
| - CSA_ASSERT(this, TaggedIsSmi(length));
|
| -
|
| - // byte_length can be -0, get rid of it.
|
| - byte_length =
|
| - ToInteger(context, byte_length, CodeStubAssembler::kTruncateMinusZero);
|
| -
|
| - GotoIfNot(IsNull(maybe_buffer), &setup_holder);
|
| - // If the buffer is null, then we need a Smi byte_length. The caller
|
| - // guarantees this is the case, because when byte_length >
|
| - // TypedArrayMaxSizeInHeap, a buffer is allocated and passed in here.
|
| - CSA_ASSERT(this, TaggedIsSmi(byte_length));
|
| - Goto(&setup_holder);
|
| -
|
| - Bind(&setup_holder);
|
| - {
|
| - LoadMapAndElementsSize(holder, &fixed_typed_map, &element_size);
|
| - // Setup the holder (JSArrayBufferView).
|
| - // - Set the length.
|
| - // - Set the byte_offset.
|
| - // - Set the byte_length.
|
| - // - Set InternalFields to 0.
|
| - StoreObjectField(holder, JSTypedArray::kLengthOffset, length);
|
| - StoreObjectField(holder, JSArrayBufferView::kByteOffsetOffset, byte_offset);
|
| - StoreObjectField(holder, JSArrayBufferView::kByteLengthOffset, byte_length);
|
| - for (int offset = JSTypedArray::kSize;
|
| - offset < JSTypedArray::kSizeWithInternalFields;
|
| - offset += kPointerSize) {
|
| - StoreObjectField(holder, offset, SmiConstant(Smi::kZero));
|
| - }
|
| -
|
| - Branch(IsNull(maybe_buffer), &alloc_array_buffer, &attach_buffer);
|
| - }
|
| -
|
| - Bind(&alloc_array_buffer);
|
| - {
|
| - // Allocate a new ArrayBuffer and initialize it with empty properties and
|
| - // elements.
|
| - Node* const native_context = LoadNativeContext(context);
|
| - Node* const map =
|
| - LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX);
|
| - Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
|
| -
|
| - Node* const buffer = Allocate(JSArrayBuffer::kSizeWithInternalFields);
|
| - StoreMapNoWriteBarrier(buffer, map);
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArray::kPropertiesOffset,
|
| - empty_fixed_array);
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArray::kElementsOffset,
|
| - empty_fixed_array);
|
| - // Setup the ArrayBuffer.
|
| - // - Set BitField to 0.
|
| - // - Set IsExternal and IsNeuterable bits of BitFieldSlot.
|
| - // - Set the byte_length field to byte_length.
|
| - // - Set backing_store to null/Smi(0).
|
| - // - Set all internal fields to Smi(0).
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldSlot,
|
| - SmiConstant(Smi::kZero));
|
| - int32_t bitfield_value = (1 << JSArrayBuffer::IsExternal::kShift) |
|
| - (1 << JSArrayBuffer::IsNeuterable::kShift);
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldOffset,
|
| - Int32Constant(bitfield_value),
|
| - MachineRepresentation::kWord32);
|
| -
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kByteLengthOffset,
|
| - byte_length);
|
| - StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBackingStoreOffset,
|
| - SmiConstant(Smi::kZero));
|
| - for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
|
| - int offset = JSArrayBuffer::kSize + i * kPointerSize;
|
| - StoreObjectFieldNoWriteBarrier(buffer, offset, SmiConstant(Smi::kZero));
|
| - }
|
| -
|
| - StoreObjectField(holder, JSArrayBufferView::kBufferOffset, buffer);
|
| -
|
| - // Check the alignment.
|
| - GotoIf(SmiEqual(SmiMod(element_size.value(), SmiConstant(kObjectAlignment)),
|
| - SmiConstant(0)),
|
| - &aligned);
|
| -
|
| - // Fix alignment if needed.
|
| - DCHECK_EQ(0, FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask);
|
| - Node* aligned_header_size =
|
| - IntPtrConstant(FixedTypedArrayBase::kHeaderSize + kObjectAlignmentMask);
|
| - Node* size = IntPtrAdd(SmiToWord(byte_length), aligned_header_size);
|
| - total_size.Bind(WordAnd(size, IntPtrConstant(~kObjectAlignmentMask)));
|
| - Goto(&allocate_elements);
|
| - }
|
| -
|
| - Bind(&aligned);
|
| - {
|
| - Node* header_size = IntPtrConstant(FixedTypedArrayBase::kHeaderSize);
|
| - total_size.Bind(IntPtrAdd(SmiToWord(byte_length), header_size));
|
| - Goto(&allocate_elements);
|
| - }
|
| -
|
| - Bind(&allocate_elements);
|
| - {
|
| - // Allocate a FixedTypedArray and set the length, base pointer and external
|
| - // pointer.
|
| - CSA_ASSERT(this, IsRegularHeapObjectSize(total_size.value()));
|
| - Node* elements = Allocate(total_size.value());
|
| -
|
| - StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
|
| - StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
|
| - StoreObjectFieldNoWriteBarrier(
|
| - elements, FixedTypedArrayBase::kBasePointerOffset, elements);
|
| - StoreObjectFieldNoWriteBarrier(elements,
|
| - FixedTypedArrayBase::kExternalPointerOffset,
|
| - IntPtrConstant(fta_base_data_offset),
|
| - MachineType::PointerRepresentation());
|
| -
|
| - StoreObjectField(holder, JSObject::kElementsOffset, elements);
|
| -
|
| - GotoIf(IsFalse(initialize), &done);
|
| - // Initialize the backing store by filling it with 0s.
|
| - Node* backing_store = IntPtrAdd(BitcastTaggedToWord(elements),
|
| - IntPtrConstant(fta_base_data_offset));
|
| - // Call out to memset to perform initialization.
|
| - Node* memset =
|
| - ExternalConstant(ExternalReference::libc_memset_function(isolate()));
|
| - CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
|
| - MachineType::IntPtr(), MachineType::UintPtr(), memset,
|
| - backing_store, IntPtrConstant(0), SmiToWord(byte_length));
|
| - Goto(&done);
|
| - }
|
| -
|
| - Bind(&attach_buffer);
|
| - {
|
| - StoreObjectField(holder, JSArrayBufferView::kBufferOffset, maybe_buffer);
|
| -
|
| - Node* elements = Allocate(FixedTypedArrayBase::kHeaderSize);
|
| - StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
|
| - StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
|
| - StoreObjectFieldNoWriteBarrier(
|
| - elements, FixedTypedArrayBase::kBasePointerOffset, SmiConstant(0));
|
| -
|
| - Variable external_pointer(this, MachineType::PointerRepresentation());
|
| - Node* backing_store =
|
| - LoadObjectField(maybe_buffer, JSArrayBuffer::kBackingStoreOffset,
|
| - MachineType::Pointer());
|
| -
|
| - CalculateExternalPointer(backing_store, byte_offset, &external_pointer);
|
| - StoreObjectFieldNoWriteBarrier(
|
| - elements, FixedTypedArrayBase::kExternalPointerOffset,
|
| - external_pointer.value(), MachineType::PointerRepresentation());
|
| -
|
| - StoreObjectField(holder, JSObject::kElementsOffset, elements);
|
| - Goto(&done);
|
| - }
|
| -
|
| - Bind(&done);
|
| - Return(UndefinedConstant());
|
| -}
|
| -
|
| -TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
|
| - Node* const holder = Parameter(1);
|
| - Node* length = Parameter(2);
|
| - Node* const maybe_buffer = Parameter(3);
|
| - Node* const byte_offset = Parameter(4);
|
| - Node* byte_length = Parameter(5);
|
| - Node* const initialize = Parameter(6);
|
| - Node* const context = Parameter(9);
|
| -
|
| - DoInitialize(holder, length, maybe_buffer, byte_offset, byte_length,
|
| - initialize, context);
|
| -}
|
| -
|
| // -----------------------------------------------------------------------------
|
| // ES6 section 22.2 TypedArray Objects
|
|
|
| -// ES6 section 22.2.4.2 TypedArray ( length )
|
| -TF_BUILTIN(TypedArrayConstructByLength, TypedArrayBuiltinsAssembler) {
|
| - // We know that holder cannot be an object if this builtin was called.
|
| - Node* holder = Parameter(1);
|
| - Node* length = Parameter(2);
|
| - Node* element_size = Parameter(3);
|
| - Node* context = Parameter(6);
|
| -
|
| - Variable maybe_buffer(this, MachineRepresentation::kTagged);
|
| - maybe_buffer.Bind(NullConstant());
|
| - Node* byte_offset = SmiConstant(0);
|
| - Node* initialize = BooleanConstant(true);
|
| -
|
| - Label external_buffer(this), call_init(this), invalid_length(this);
|
| -
|
| - length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
|
| - // The maximum length of a TypedArray is MaxSmi().
|
| - // Note: this is not per spec, but rather a constraint of our current
|
| - // representation (which uses smi's).
|
| - GotoIf(TaggedIsNotSmi(length), &invalid_length);
|
| - GotoIf(SmiLessThan(length, SmiConstant(0)), &invalid_length);
|
| -
|
| - // For byte_length < typed_array_max_size_in_heap, we allocate the buffer on
|
| - // the heap. Otherwise we allocate it externally and attach it.
|
| - Node* byte_length = SmiMul(length, element_size);
|
| - GotoIf(TaggedIsNotSmi(byte_length), &external_buffer);
|
| - Branch(SmiLessThanOrEqual(byte_length,
|
| - SmiConstant(FLAG_typed_array_max_size_in_heap)),
|
| - &call_init, &external_buffer);
|
| -
|
| - Bind(&external_buffer);
|
| - {
|
| - Node* const buffer_constructor = LoadContextElement(
|
| - LoadNativeContext(context), Context::ARRAY_BUFFER_FUN_INDEX);
|
| - maybe_buffer.Bind(ConstructJS(CodeFactory::Construct(isolate()), context,
|
| - buffer_constructor, byte_length));
|
| - Goto(&call_init);
|
| - }
|
| -
|
| - Bind(&call_init);
|
| - {
|
| - DoInitialize(holder, length, maybe_buffer.value(), byte_offset, byte_length,
|
| - initialize, context);
|
| - }
|
| -
|
| - Bind(&invalid_length);
|
| - {
|
| - CallRuntime(Runtime::kThrowRangeError, context,
|
| - SmiConstant(MessageTemplate::kInvalidTypedArrayLength));
|
| - Unreachable();
|
| - }
|
| -}
|
| -
|
| -// ES6 section 22.2.4.5 TypedArray ( buffer [ , byteOffset [ , length ] ] )
|
| -TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
|
| - Node* const holder = Parameter(1);
|
| - Node* const buffer = Parameter(2);
|
| - Node* byte_offset = Parameter(3);
|
| - Node* const length = Parameter(4);
|
| - Node* const element_size = Parameter(5);
|
| - CSA_ASSERT(this, TaggedIsSmi(element_size));
|
| - Node* const context = Parameter(8);
|
| - Node* const initialize = BooleanConstant(true);
|
| -
|
| - Variable new_byte_length(this, MachineRepresentation::kTagged,
|
| - SmiConstant(0));
|
| -
|
| - Label start_offset_error(this), byte_length_error(this),
|
| - invalid_offset_error(this);
|
| - Label call_init(this), invalid_length(this), length_undefined(this),
|
| - length_defined(this);
|
| -
|
| - Callable add = CodeFactory::Add(isolate());
|
| - Callable div = CodeFactory::Divide(isolate());
|
| - Callable equal = CodeFactory::Equal(isolate());
|
| - Callable greater_than = CodeFactory::GreaterThan(isolate());
|
| - Callable less_than = CodeFactory::LessThan(isolate());
|
| - Callable mod = CodeFactory::Modulus(isolate());
|
| - Callable sub = CodeFactory::Subtract(isolate());
|
| -
|
| - byte_offset =
|
| - ToInteger(context, byte_offset, CodeStubAssembler::kTruncateMinusZero);
|
| - GotoIf(IsTrue(CallStub(less_than, context, byte_offset, SmiConstant(0))),
|
| - &invalid_length);
|
| -
|
| - Node* remainder = CallStub(mod, context, byte_offset, element_size);
|
| - // Remainder can be a heap number.
|
| - GotoIf(IsFalse(CallStub(equal, context, remainder, SmiConstant(0))),
|
| - &start_offset_error);
|
| -
|
| - // TODO(petermarshall): Throw on detached typedArray.
|
| - Branch(IsUndefined(length), &length_undefined, &length_defined);
|
| -
|
| - Bind(&length_undefined);
|
| - {
|
| - Node* buffer_byte_length =
|
| - LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset);
|
| -
|
| - Node* remainder = CallStub(mod, context, buffer_byte_length, element_size);
|
| - // Remainder can be a heap number.
|
| - GotoIf(IsFalse(CallStub(equal, context, remainder, SmiConstant(0))),
|
| - &byte_length_error);
|
| -
|
| - new_byte_length.Bind(
|
| - CallStub(sub, context, buffer_byte_length, byte_offset));
|
| -
|
| - Branch(IsTrue(CallStub(less_than, context, new_byte_length.value(),
|
| - SmiConstant(0))),
|
| - &invalid_offset_error, &call_init);
|
| - }
|
| -
|
| - Bind(&length_defined);
|
| - {
|
| - Node* new_length = ToSmiIndex(length, context, &invalid_length);
|
| - 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);
|
| -
|
| - Node* end = CallStub(add, context, byte_offset, new_byte_length.value());
|
| -
|
| - Branch(IsTrue(CallStub(greater_than, context, end, buffer_byte_length)),
|
| - &invalid_length, &call_init);
|
| - }
|
| -
|
| - Bind(&call_init);
|
| - {
|
| - Node* new_length =
|
| - CallStub(div, context, new_byte_length.value(), element_size);
|
| - // Force the result into a Smi, or throw a range error if it doesn't fit.
|
| - new_length = ToSmiIndex(new_length, context, &invalid_length);
|
| -
|
| - DoInitialize(holder, new_length, buffer, byte_offset,
|
| - new_byte_length.value(), initialize, context);
|
| - }
|
| -
|
| - Bind(&invalid_offset_error);
|
| - {
|
| - CallRuntime(Runtime::kThrowRangeError, context,
|
| - SmiConstant(MessageTemplate::kInvalidOffset), byte_offset);
|
| - Unreachable();
|
| - }
|
| -
|
| - Bind(&start_offset_error);
|
| - {
|
| - Node* holder_map = LoadMap(holder);
|
| - Node* problem_string = HeapConstant(
|
| - factory()->NewStringFromAsciiChecked("start offset", TENURED));
|
| - CallRuntime(Runtime::kThrowInvalidTypedArrayAlignment, context, holder_map,
|
| - problem_string);
|
| -
|
| - Unreachable();
|
| - }
|
| -
|
| - Bind(&byte_length_error);
|
| - {
|
| - Node* holder_map = LoadMap(holder);
|
| - Node* problem_string = HeapConstant(
|
| - factory()->NewStringFromAsciiChecked("byte length", TENURED));
|
| - CallRuntime(Runtime::kThrowInvalidTypedArrayAlignment, context, holder_map,
|
| - problem_string);
|
| -
|
| - Unreachable();
|
| - }
|
| -
|
| - Bind(&invalid_length);
|
| - {
|
| - CallRuntime(Runtime::kThrowRangeError, context,
|
| - SmiConstant(MessageTemplate::kInvalidTypedArrayLength));
|
| - Unreachable();
|
| - }
|
| -}
|
| -
|
| // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
|
| BUILTIN(TypedArrayPrototypeBuffer) {
|
| HandleScope scope(isolate);
|
| @@ -476,119 +21,6 @@ BUILTIN(TypedArrayPrototypeBuffer) {
|
| return *typed_array->GetBuffer();
|
| }
|
|
|
| -void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeGetter(
|
| - const char* method_name, int object_offset) {
|
| - Node* receiver = Parameter(0);
|
| - Node* context = Parameter(3);
|
| -
|
| - // Check if the {receiver} is actually a JSTypedArray.
|
| - Label receiver_is_incompatible(this, Label::kDeferred);
|
| - GotoIf(TaggedIsSmi(receiver), &receiver_is_incompatible);
|
| - GotoIfNot(HasInstanceType(receiver, JS_TYPED_ARRAY_TYPE),
|
| - &receiver_is_incompatible);
|
| -
|
| - // 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));
|
| - }
|
| -
|
| - Bind(&receiver_is_incompatible);
|
| - {
|
| - // The {receiver} is not a valid JSTypedArray.
|
| - CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
|
| - HeapConstant(
|
| - factory()->NewStringFromAsciiChecked(method_name, TENURED)),
|
| - receiver);
|
| - Unreachable();
|
| - }
|
| -}
|
| -
|
| -// ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
|
| -TF_BUILTIN(TypedArrayPrototypeByteLength, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.byteLength",
|
| - JSTypedArray::kByteLengthOffset);
|
| -}
|
| -
|
| -// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
|
| -TF_BUILTIN(TypedArrayPrototypeByteOffset, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.byteOffset",
|
| - JSTypedArray::kByteOffsetOffset);
|
| -}
|
| -
|
| -// ES6 section 22.2.3.18 get %TypedArray%.prototype.length
|
| -TF_BUILTIN(TypedArrayPrototypeLength, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.length",
|
| - JSTypedArray::kLengthOffset);
|
| -}
|
| -
|
| -template <IterationKind kIterationKind>
|
| -void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeIterationMethod(
|
| - const char* method_name) {
|
| - Node* receiver = Parameter(0);
|
| - Node* context = Parameter(3);
|
| -
|
| - Label throw_bad_receiver(this, Label::kDeferred);
|
| - Label throw_typeerror(this, Label::kDeferred);
|
| -
|
| - GotoIf(TaggedIsSmi(receiver), &throw_bad_receiver);
|
| -
|
| - Node* map = LoadMap(receiver);
|
| - Node* instance_type = LoadMapInstanceType(map);
|
| - GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
| - &throw_bad_receiver);
|
| -
|
| - // 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(CreateArrayIterator(receiver, map, instance_type, context,
|
| - kIterationKind));
|
| -
|
| - Variable var_message(this, MachineRepresentation::kTagged);
|
| - Bind(&throw_bad_receiver);
|
| - var_message.Bind(SmiConstant(MessageTemplate::kNotTypedArray));
|
| - Goto(&throw_typeerror);
|
| -
|
| - Bind(&if_receiverisneutered);
|
| - var_message.Bind(
|
| - SmiConstant(Smi::FromInt(MessageTemplate::kDetachedOperation)));
|
| - Goto(&throw_typeerror);
|
| -
|
| - Bind(&throw_typeerror);
|
| - {
|
| - Node* method_arg = HeapConstant(
|
| - isolate()->factory()->NewStringFromAsciiChecked(method_name, TENURED));
|
| - Node* result = CallRuntime(Runtime::kThrowTypeError, context,
|
| - var_message.value(), method_arg);
|
| - Return(result);
|
| - }
|
| -}
|
| -
|
| -TF_BUILTIN(TypedArrayPrototypeValues, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeIterationMethod<IterationKind::kValues>(
|
| - "%TypedArray%.prototype.values()");
|
| -}
|
| -
|
| -TF_BUILTIN(TypedArrayPrototypeEntries, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeIterationMethod<IterationKind::kEntries>(
|
| - "%TypedArray%.prototype.entries()");
|
| -}
|
| -
|
| -TF_BUILTIN(TypedArrayPrototypeKeys, TypedArrayBuiltinsAssembler) {
|
| - GenerateTypedArrayPrototypeIterationMethod<IterationKind::kKeys>(
|
| - "%TypedArray%.prototype.keys()");
|
| -}
|
| -
|
| namespace {
|
|
|
| int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
|
|
|