Index: src/builtins/builtins-array.cc |
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc |
index b5190e66bc9d1b1d9dc37e6b3bece61ccf5be399..10515c780c3ee4255faad148f60a88a4cfa8f5d0 100644 |
--- a/src/builtins/builtins-array.cc |
+++ b/src/builtins/builtins-array.cc |
@@ -6,6 +6,7 @@ |
#include "src/builtins/builtins-utils.h" |
#include "src/code-factory.h" |
+#include "src/contexts.h" |
#include "src/elements.h" |
namespace v8 { |
@@ -2067,5 +2068,523 @@ void Builtins::Generate_ArrayIndexOf(CodeStubAssembler* assembler) { |
array, search_element, start_from)); |
} |
+namespace { |
+ |
+template <IterationKind kIterationKind> |
+void Generate_ArrayPrototypeIterationMethod(CodeStubAssembler* assembler) { |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Label Label; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Node* receiver = assembler->Parameter(0); |
+ Node* context = assembler->Parameter(3); |
+ |
+ Variable var_array(assembler, MachineRepresentation::kTagged); |
+ Variable var_map(assembler, MachineRepresentation::kTagged); |
+ Variable var_type(assembler, MachineRepresentation::kWord32); |
+ |
+ Label if_isnotobject(assembler, Label::kDeferred); |
+ Label create_array_iterator(assembler); |
+ |
+ assembler->GotoIf(assembler->TaggedIsSmi(receiver), &if_isnotobject); |
+ var_array.Bind(receiver); |
+ var_map.Bind(assembler->LoadMap(receiver)); |
+ var_type.Bind(assembler->LoadMapInstanceType(var_map.value())); |
+ assembler->Branch(assembler->IsJSReceiverInstanceType(var_type.value()), |
+ &create_array_iterator, &if_isnotobject); |
+ |
+ assembler->Bind(&if_isnotobject); |
+ { |
+ Callable callable = CodeFactory::ToObject(assembler->isolate()); |
+ Node* result = assembler->CallStub(callable, context, receiver); |
+ var_array.Bind(result); |
+ var_map.Bind(assembler->LoadMap(result)); |
+ var_type.Bind(assembler->LoadMapInstanceType(var_map.value())); |
+ assembler->Goto(&create_array_iterator); |
+ } |
+ |
+ assembler->Bind(&create_array_iterator); |
+ assembler->Return(assembler->CreateArrayIterator( |
+ var_array.value(), var_map.value(), var_type.value(), context, |
+ kIterationKind)); |
+} |
+ |
+} // namespace |
+ |
+void Builtins::Generate_ArrayPrototypeValues(CodeStubAssembler* assembler) { |
+ Generate_ArrayPrototypeIterationMethod<IterationKind::kValues>(assembler); |
+} |
+ |
+void Builtins::Generate_ArrayPrototypeEntries(CodeStubAssembler* assembler) { |
+ Generate_ArrayPrototypeIterationMethod<IterationKind::kEntries>(assembler); |
+} |
+ |
+void Builtins::Generate_ArrayPrototypeKeys(CodeStubAssembler* assembler) { |
+ Generate_ArrayPrototypeIterationMethod<IterationKind::kKeys>(assembler); |
+} |
+ |
+void Builtins::Generate_ArrayIteratorPrototypeNext( |
+ CodeStubAssembler* assembler) { |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Label Label; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Node* iterator = assembler->Parameter(0); |
+ Node* context = assembler->Parameter(3); |
+ |
+ Variable var_value(assembler, MachineRepresentation::kTagged); |
+ Variable var_done(assembler, MachineRepresentation::kTagged); |
+ |
+ // Required, or else `throw_bad_receiver` fails a DCHECK due to these |
+ // variables not being bound along all paths, despite not being used. |
+ var_done.Bind(assembler->TrueConstant()); |
+ var_value.Bind(assembler->UndefinedConstant()); |
+ |
+ Label throw_bad_receiver(assembler, Label::kDeferred); |
+ Label set_done(assembler); |
+ Label allocate_key_result(assembler); |
+ Label allocate_entry_if_needed(assembler); |
+ Label allocate_iterator_result(assembler); |
+ Label generic_values(assembler); |
+ |
+ // If O does not have all of the internal slots of an Array Iterator Instance |
+ // (22.1.5.3), throw a TypeError exception |
+ assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver); |
+ Node* instance_type = assembler->LoadInstanceType(iterator); |
+ assembler->GotoIf( |
+ assembler->Uint32LessThan( |
+ assembler->Int32Constant(LAST_ARRAY_ITERATOR_TYPE - |
+ FIRST_ARRAY_ITERATOR_TYPE), |
+ assembler->Int32Sub(instance_type, assembler->Int32Constant( |
+ FIRST_ARRAY_ITERATOR_TYPE))), |
+ &throw_bad_receiver); |
+ |
+ // Let a be O.[[IteratedObject]]. |
+ Node* array = assembler->LoadObjectField( |
+ iterator, JSArrayIterator::kIteratedObjectOffset); |
+ |
+ // Let index be O.[[ArrayIteratorNextIndex]]. |
+ Node* index = |
+ assembler->LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset); |
+ Node* orig_map = assembler->LoadObjectField( |
+ iterator, JSArrayIterator::kIteratedObjectMapOffset); |
+ Node* array_map = assembler->LoadMap(array); |
+ |
+ Label if_isfastarray(assembler), if_isnotfastarray(assembler); |
+ |
+ assembler->Branch(assembler->WordEqual(orig_map, array_map), &if_isfastarray, |
+ &if_isnotfastarray); |
+ |
+ assembler->Bind(&if_isfastarray); |
+ { |
+ assembler->Assert( |
+ assembler->Word32Equal(assembler->LoadMapInstanceType(array_map), |
+ assembler->Int32Constant(JS_ARRAY_TYPE))); |
+ |
+ Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset); |
+ |
+ assembler->Assert(assembler->TaggedIsSmi(length)); |
+ assembler->Assert(assembler->TaggedIsSmi(index)); |
+ |
+ assembler->GotoUnless(assembler->SmiBelow(index, length), &set_done); |
+ |
+ Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ iterator, JSArrayIterator::kNextIndexOffset, |
+ assembler->IntPtrAdd(assembler->BitcastTaggedToWord(index), |
+ assembler->BitcastTaggedToWord(one))); |
+ |
+ var_done.Bind(assembler->FalseConstant()); |
+ Node* elements = assembler->LoadElements(array); |
+ |
+ static int32_t kInstanceType[] = { |
+ JS_FAST_ARRAY_KEY_ITERATOR_TYPE, |
+ JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, |
+ }; |
+ |
+ Label packed_object_values(assembler), holey_object_values(assembler), |
+ packed_double_values(assembler), holey_double_values(assembler); |
+ Label* kInstanceTypeHandlers[] = { |
+ &allocate_key_result, &packed_object_values, &holey_object_values, |
+ &packed_object_values, &holey_object_values, &packed_double_values, |
+ &holey_double_values, &packed_object_values, &holey_object_values, |
+ &packed_object_values, &holey_object_values, &packed_double_values, |
+ &holey_double_values}; |
+ |
+ assembler->Switch(instance_type, &throw_bad_receiver, kInstanceType, |
+ kInstanceTypeHandlers, arraysize(kInstanceType)); |
+ |
+ assembler->Bind(&packed_object_values); |
+ { |
+ var_value.Bind(assembler->LoadFixedArrayElement( |
+ elements, index, 0, CodeStubAssembler::SMI_PARAMETERS)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&packed_double_values); |
+ { |
+ Node* value = assembler->LoadFixedDoubleArrayElement( |
+ elements, index, MachineType::Float64(), 0, |
+ CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->AllocateHeapNumberWithValue(value)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&holey_object_values); |
+ { |
+ // Check the array_protector cell, and take the slow path if it's invalid. |
+ Node* invalid = |
+ assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorInvalid)); |
+ Node* cell = assembler->LoadRoot(Heap::kArrayProtectorRootIndex); |
+ Node* cell_value = |
+ assembler->LoadObjectField(cell, PropertyCell::kValueOffset); |
+ assembler->GotoIf(assembler->WordEqual(cell_value, invalid), |
+ &generic_values); |
+ |
+ var_value.Bind(assembler->UndefinedConstant()); |
+ Node* value = assembler->LoadFixedArrayElement( |
+ elements, index, 0, CodeStubAssembler::SMI_PARAMETERS); |
+ assembler->GotoIf( |
+ assembler->WordEqual(value, assembler->TheHoleConstant()), |
+ &allocate_entry_if_needed); |
+ var_value.Bind(value); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&holey_double_values); |
+ { |
+ // Check the array_protector cell, and take the slow path if it's invalid. |
+ Node* invalid = |
+ assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorInvalid)); |
+ Node* cell = assembler->LoadRoot(Heap::kArrayProtectorRootIndex); |
+ Node* cell_value = |
+ assembler->LoadObjectField(cell, PropertyCell::kValueOffset); |
+ assembler->GotoIf(assembler->WordEqual(cell_value, invalid), |
+ &generic_values); |
+ |
+ var_value.Bind(assembler->UndefinedConstant()); |
+ Node* value = assembler->LoadFixedDoubleArrayElement( |
+ elements, index, MachineType::Float64(), 0, |
+ CodeStubAssembler::SMI_PARAMETERS, &allocate_entry_if_needed); |
+ var_value.Bind(assembler->AllocateHeapNumberWithValue(value)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ } |
+ |
+ assembler->Bind(&if_isnotfastarray); |
+ { |
+ Label if_istypedarray(assembler), if_isgeneric(assembler); |
+ |
+ // If a is undefined, return CreateIterResultObject(undefined, true) |
+ assembler->GotoIf( |
+ assembler->WordEqual(array, assembler->UndefinedConstant()), |
+ &allocate_iterator_result); |
+ |
+ Node* array_type = assembler->LoadInstanceType(array); |
+ assembler->Branch( |
+ assembler->Word32Equal(array_type, |
+ assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)), |
+ &if_istypedarray, &if_isgeneric); |
+ |
+ assembler->Bind(&if_isgeneric); |
+ { |
+ Node* length = nullptr; |
+ { |
+ Variable var_length(assembler, MachineRepresentation::kTagged); |
+ Label if_isarray(assembler), if_isnotarray(assembler), done(assembler); |
+ assembler->Branch( |
+ assembler->Word32Equal(array_type, |
+ assembler->Int32Constant(JS_ARRAY_TYPE)), |
+ &if_isarray, &if_isnotarray); |
+ |
+ assembler->Bind(&if_isarray); |
+ { |
+ var_length.Bind( |
+ assembler->LoadObjectField(array, JSArray::kLengthOffset)); |
+ assembler->Goto(&done); |
+ } |
+ |
+ assembler->Bind(&if_isnotarray); |
+ { |
+ Node* length_string = assembler->HeapConstant( |
+ assembler->isolate()->factory()->length_string()); |
+ Callable get_property = |
+ CodeFactory::GetProperty(assembler->isolate()); |
+ Node* length = |
+ assembler->CallStub(get_property, context, array, length_string); |
+ Callable to_length = CodeFactory::ToLength(assembler->isolate()); |
+ var_length.Bind(assembler->CallStub(to_length, context, length)); |
+ assembler->Goto(&done); |
+ } |
+ |
+ assembler->Bind(&done); |
+ length = var_length.value(); |
+ } |
+ |
+ assembler->GotoUnlessNumberLessThan(index, length, &set_done); |
+ |
+ assembler->StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, |
+ assembler->NumberInc(index)); |
+ var_done.Bind(assembler->FalseConstant()); |
+ |
+ assembler->Branch( |
+ assembler->Uint32LessThanOrEqual( |
+ instance_type, |
+ assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)), |
+ &allocate_key_result, &generic_values); |
+ |
+ assembler->Bind(&generic_values); |
+ { |
+ Callable get_property = CodeFactory::GetProperty(assembler->isolate()); |
+ var_value.Bind( |
+ assembler->CallStub(get_property, context, array, index)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ } |
+ |
+ assembler->Bind(&if_istypedarray); |
+ { |
+ Node* length = nullptr; |
+ { |
+ Variable var_length(assembler, MachineRepresentation::kTagged); |
+ Label if_isdetached(assembler, Label::kDeferred), |
+ if_isnotdetached(assembler), done(assembler); |
+ |
+ Node* buffer = |
+ assembler->LoadObjectField(array, JSTypedArray::kBufferOffset); |
+ assembler->Branch(assembler->IsDetachedBuffer(buffer), &if_isdetached, |
+ &if_isnotdetached); |
+ |
+ assembler->Bind(&if_isnotdetached); |
+ { |
+ var_length.Bind( |
+ assembler->LoadObjectField(array, JSTypedArray::kLengthOffset)); |
+ assembler->Goto(&done); |
+ } |
+ |
+ assembler->Bind(&if_isdetached); |
+ { |
+ var_length.Bind(assembler->SmiConstant(Smi::kZero)); |
+ assembler->Goto(&done); |
+ } |
+ |
+ assembler->Bind(&done); |
+ length = var_length.value(); |
+ } |
+ assembler->Assert(assembler->TaggedIsSmi(length)); |
+ assembler->Assert(assembler->TaggedIsSmi(index)); |
+ |
+ assembler->GotoUnless(assembler->SmiBelow(index, length), &set_done); |
+ |
+ Node* one = assembler->SmiConstant(Smi::FromInt(1)); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ iterator, JSArrayIterator::kNextIndexOffset, |
+ assembler->IntPtrAdd(assembler->BitcastTaggedToWord(index), |
+ assembler->BitcastTaggedToWord(one))); |
+ var_done.Bind(assembler->FalseConstant()); |
+ |
+ Node* elements = assembler->LoadElements(array); |
+ Node* base_ptr = assembler->LoadObjectField( |
+ elements, FixedTypedArrayBase::kBasePointerOffset); |
+ Node* external_ptr = assembler->LoadObjectField( |
+ elements, FixedTypedArrayBase::kExternalPointerOffset); |
+ Node* data_ptr = assembler->IntPtrAdd(base_ptr, external_ptr); |
+ |
+ static int32_t kInstanceType[] = { |
+ JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, |
+ JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE, |
+ JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_INT8_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_INT16_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_INT32_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE, |
+ JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE, |
+ }; |
+ |
+ Label uint8_values(assembler), int8_values(assembler), |
+ uint16_values(assembler), int16_values(assembler), |
+ uint32_values(assembler), int32_values(assembler), |
+ float32_values(assembler), float64_values(assembler); |
+ Label* kInstanceTypeHandlers[] = { |
+ &allocate_key_result, &uint8_values, &uint8_values, |
+ &int8_values, &uint16_values, &int16_values, |
+ &uint32_values, &int32_values, &float32_values, |
+ &float64_values, &uint8_values, &uint8_values, |
+ &int8_values, &uint16_values, &int16_values, |
+ &uint32_values, &int32_values, &float32_values, |
+ &float64_values, |
+ }; |
+ |
+ var_done.Bind(assembler->FalseConstant()); |
+ assembler->Switch(instance_type, &throw_bad_receiver, kInstanceType, |
+ kInstanceTypeHandlers, arraysize(kInstanceType)); |
+ |
+ assembler->Bind(&uint8_values); |
+ { |
+ Node* value_uint8 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, UINT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->SmiFromWord(value_uint8)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&int8_values); |
+ { |
+ Node* value_int8 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, INT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->SmiFromWord(value_int8)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&uint16_values); |
+ { |
+ Node* value_uint16 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, UINT16_ELEMENTS, |
+ CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->SmiFromWord(value_uint16)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&int16_values); |
+ { |
+ Node* value_int16 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, INT16_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->SmiFromWord(value_int16)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ |
+ assembler->Bind(&uint32_values); |
+ { |
+ Node* value_uint32 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, UINT32_ELEMENTS, |
+ CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->ChangeUint32ToTagged(value_uint32)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ assembler->Bind(&int32_values); |
+ { |
+ Node* value_int32 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, INT32_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->ChangeInt32ToTagged(value_int32)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ assembler->Bind(&float32_values); |
+ { |
+ Node* value_float32 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, FLOAT32_ELEMENTS, |
+ CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->AllocateHeapNumberWithValue( |
+ assembler->ChangeFloat32ToFloat64(value_float32))); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ assembler->Bind(&float64_values); |
+ { |
+ Node* value_float64 = assembler->LoadFixedTypedArrayElement( |
+ data_ptr, index, FLOAT64_ELEMENTS, |
+ CodeStubAssembler::SMI_PARAMETERS); |
+ var_value.Bind(assembler->AllocateHeapNumberWithValue(value_float64)); |
+ assembler->Goto(&allocate_entry_if_needed); |
+ } |
+ } |
+ } |
+ |
+ assembler->Bind(&set_done); |
+ { |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ iterator, JSArrayIterator::kIteratedObjectOffset, |
+ assembler->UndefinedConstant()); |
+ assembler->Goto(&allocate_iterator_result); |
+ } |
+ |
+ assembler->Bind(&allocate_key_result); |
+ { |
+ var_value.Bind(index); |
+ var_done.Bind(assembler->FalseConstant()); |
+ assembler->Goto(&allocate_iterator_result); |
+ } |
+ |
+ assembler->Bind(&allocate_entry_if_needed); |
+ { |
+ assembler->GotoIf( |
+ assembler->Int32GreaterThan( |
+ instance_type, |
+ assembler->Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)), |
+ &allocate_iterator_result); |
+ |
+ Node* elements = assembler->AllocateFixedArray(FAST_ELEMENTS, |
+ assembler->Int32Constant(2)); |
+ assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(0), |
+ index, SKIP_WRITE_BARRIER); |
+ assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(1), |
+ var_value.value(), SKIP_WRITE_BARRIER); |
+ |
+ Node* entry = assembler->Allocate(JSArray::kSize); |
+ Node* map = assembler->LoadContextElement( |
+ assembler->LoadNativeContext(context), |
+ Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX); |
+ |
+ assembler->StoreMapNoWriteBarrier(entry, map); |
+ assembler->StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset, |
+ Heap::kEmptyFixedArrayRootIndex); |
+ assembler->StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset, |
+ elements); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ entry, JSArray::kLengthOffset, assembler->SmiConstant(Smi::FromInt(2))); |
+ |
+ var_value.Bind(entry); |
+ assembler->Goto(&allocate_iterator_result); |
+ } |
+ |
+ assembler->Bind(&allocate_iterator_result); |
+ { |
+ Node* result = assembler->Allocate(JSIteratorResult::kSize); |
+ Node* map = |
+ assembler->LoadContextElement(assembler->LoadNativeContext(context), |
+ Context::ITERATOR_RESULT_MAP_INDEX); |
+ assembler->StoreMapNoWriteBarrier(result, map); |
+ assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, |
+ Heap::kEmptyFixedArrayRootIndex); |
+ assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, |
+ Heap::kEmptyFixedArrayRootIndex); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ result, JSIteratorResult::kValueOffset, var_value.value()); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ result, JSIteratorResult::kDoneOffset, var_done.value()); |
+ assembler->Return(result); |
+ } |
+ |
+ assembler->Bind(&throw_bad_receiver); |
+ { |
+ // The {receiver} is not a valid JSArrayIterator. |
+ Node* result = assembler->CallRuntime( |
+ Runtime::kThrowIncompatibleMethodReceiver, context, |
+ assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( |
+ "Array Iterator.prototype.next", TENURED)), |
+ iterator); |
+ assembler->Return(result); |
+ } |
+} |
+ |
} // namespace internal |
} // namespace v8 |