Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Unified Diff: src/builtins/builtins-array.cc

Issue 2405253006: [builtins] implement Array.prototype[@@iterator] in TFJ builtins (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/builtins/builtins-array.cc
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index b5190e66bc9d1b1d9dc37e6b3bece61ccf5be399..7b8e5050e268b7fae474a0cd2f57d3f89dc38492 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,796 @@ void Builtins::Generate_ArrayIndexOf(CodeStubAssembler* assembler) {
array, search_element, start_from));
}
+void Builtins::Generate_ArrayPrototypeValues(CodeStubAssembler* assembler) {
Benedikt Meurer 2016/10/13 05:07:19 Do you plan to do a separate TypedArrayPrototypeVa
caitp 2016/10/13 22:32:43 I've made it so that the triplet methods (keys/val
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Label Label;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Variable var_array(assembler, MachineRepresentation::kTagged);
+ Variable var_result(assembler, MachineRepresentation::kTagged);
Benedikt Meurer 2016/10/13 05:07:20 This seems to be unused.
caitp 2016/10/13 22:32:43 I _think_ this is no longer an issue after the big
+ Variable var_map(assembler, MachineRepresentation::kTagged);
+ Variable var_map_index(assembler, MachineType::PointerRepresentation());
+
+ Label call_to_object(assembler);
+ Label check_instance_type(assembler);
+ Label if_isfastarray(assembler);
+ Label if_isgeneric(assembler);
+ Label allocate_array_iterator(assembler);
+ Label allocate_typed_array_iterator(assembler);
+
+ Node* receiver = assembler->Parameter(0);
caitp 2016/10/13 00:13:36 For reasons I don't completely understand, the for
Benedikt Meurer 2016/10/13 05:07:19 Hm, this looks like a bug somewhere. You could rep
Yang 2016/10/13 13:52:37 Doesn't ring a bell, sorry. But I'm not all that s
caitp 2016/10/13 16:12:58 It turns out, including the receiver in the intern
+ Node* context = assembler->Parameter(3);
+ Node* native_context = assembler->LoadNativeContext(context);
+
+ var_array.Bind(receiver);
+ var_result.Bind(assembler->UndefinedConstant());
+ var_map.Bind(assembler->UndefinedConstant());
+ var_map_index.Bind(assembler->IntPtrConstant(0));
Benedikt Meurer 2016/10/13 05:07:19 You don't need to bind var_map / var_map_index her
caitp 2016/10/13 22:32:43 This still happens in the new version, in CodeStub
+
+ assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
+ &check_instance_type);
+ assembler->Bind(&check_instance_type);
+ {
+ var_map.Bind(assembler->LoadMap(var_array.value()));
+ Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
+ assembler->GotoIf(
+ assembler->Int32LessThan(
+ instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
+ &call_to_object);
+
+ assembler->GotoIf(
+ assembler->WordEqual(instance_type,
+ assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+ &allocate_typed_array_iterator);
+
+ assembler->BranchIfFastJSArray(var_array.value(), context, &if_isfastarray,
+ &if_isgeneric);
+ }
+
+ assembler->Bind(&if_isfastarray);
+ {
+ Node* map_index = assembler->IntPtrAdd(
Benedikt Meurer 2016/10/13 05:07:19 Neat! But please add some STATIC_ASSERTs to guard
caitp 2016/10/13 22:32:43 ah, I think I added some comments to this stuff, b
+ assembler->IntPtrConstant(Context::FAST_ARRAY_VALUE_ITERATOR_MAP_INDEX),
+ assembler->LoadMapElementsKind(assembler->LoadMap(var_array.value())));
+ assembler->Assert(assembler->IntPtrLessThan(
+ map_index, assembler->IntPtrConstant(
+ Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX)));
+
+ var_map_index.Bind(map_index);
+ assembler->Goto(&allocate_array_iterator);
+ }
+
+ assembler->Bind(&call_to_object);
+ {
+ Callable callable = CodeFactory::ToObject(assembler->isolate());
+ Node* result = assembler->CallStub(callable, context, var_array.value());
+ var_map.Bind(assembler->LoadMap(result));
+ var_array.Bind(result);
+ assembler->Goto(&if_isgeneric);
+ }
+
+ assembler->Bind(&if_isgeneric);
+ {
+ Node* map_index =
+ assembler->IntPtrConstant(Context::FAST_ARRAY_VALUE_ITERATOR_MAP_INDEX);
+
+ var_map_index.Bind(map_index);
+ assembler->Goto(&allocate_array_iterator);
+ }
+
+ assembler->Bind(&allocate_array_iterator);
+ {
+ Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
Benedikt Meurer 2016/10/13 05:07:19 Can you add a helper method AllocateArrayIterator(
caitp 2016/10/13 22:32:44 I've added CodeStubAssembler::AllocateJSArrayItera
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, var_map_index.value(), 0,
+ CodeStubAssembler::INTPTR_PARAMETERS);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSIteratorResult::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
+ assembler->Return(iterator);
+ }
+
+ assembler->Bind(&allocate_typed_array_iterator);
+ {
+ Node* map_index = assembler->IntPtrAdd(
+ assembler->IntPtrConstant(
+ Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX),
+ assembler->Int32Sub(assembler->LoadMapElementsKind(
+ assembler->LoadMap(var_array.value())),
+ assembler->Int32Constant(UINT8_ELEMENTS)));
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kIteratedObjectOffset,
+ var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->Return(iterator);
+ }
+}
+
+void Builtins::Generate_ArrayPrototypeEntries(CodeStubAssembler* assembler) {
Benedikt Meurer 2016/10/13 05:07:19 Can you unify this with the ArrayPrototypeValues a
caitp 2016/10/13 22:32:43 Done in CodeStubAssembler::CreateArrayIterator()
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Label Label;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Variable var_array(assembler, MachineRepresentation::kTagged);
+ Variable var_result(assembler, MachineRepresentation::kTagged);
+ Variable var_map(assembler, MachineRepresentation::kTagged);
+ Variable var_map_index(assembler, MachineType::PointerRepresentation());
+
+ Label call_to_object(assembler);
+ Label check_instance_type(assembler);
+ Label if_isfastarray(assembler);
+ Label if_isgeneric(assembler);
+ Label allocate_array_iterator(assembler);
+ Label allocate_typed_array_iterator(assembler);
+
+ Node* receiver = assembler->Parameter(0);
+ Node* context = assembler->Parameter(3);
+ Node* native_context = assembler->LoadNativeContext(context);
+
+ var_array.Bind(receiver);
+ var_result.Bind(assembler->UndefinedConstant());
+ var_map.Bind(assembler->UndefinedConstant());
+ var_map_index.Bind(assembler->IntPtrConstant(0));
+
+ assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
+ &check_instance_type);
+ assembler->Bind(&check_instance_type);
+ {
+ var_map.Bind(assembler->LoadMap(var_array.value()));
+ Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
+ assembler->GotoIf(
+ assembler->Int32LessThan(
+ instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
+ &call_to_object);
+
+ assembler->GotoIf(
+ assembler->WordEqual(instance_type,
+ assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+ &allocate_typed_array_iterator);
+
+ assembler->BranchIfFastJSArray(var_array.value(), context, &if_isfastarray,
+ &if_isgeneric);
+ }
+
+ assembler->Bind(&if_isfastarray);
+ {
+ Node* map_index = assembler->IntPtrAdd(
+ assembler->IntPtrConstant(
+ Context::FAST_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX),
+ assembler->LoadMapElementsKind(assembler->LoadMap(var_array.value())));
+ assembler->Assert(assembler->IntPtrLessThan(
+ map_index, assembler->IntPtrConstant(
+ Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX)));
+
+ var_map_index.Bind(map_index);
+ assembler->Goto(&allocate_array_iterator);
+ }
+
+ assembler->Bind(&call_to_object);
+ {
+ Callable callable = CodeFactory::ToObject(assembler->isolate());
+ Node* result = assembler->CallStub(callable, context, var_array.value());
+ var_map.Bind(assembler->LoadMap(result));
+ var_array.Bind(result);
+ assembler->Goto(&if_isgeneric);
+ }
+
+ assembler->Bind(&if_isgeneric);
+ {
+ Node* map_index = assembler->IntPtrConstant(
+ Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX);
+ var_map_index.Bind(map_index);
+ assembler->Goto(&allocate_array_iterator);
+ }
+
+ assembler->Bind(&allocate_array_iterator);
+ {
+ Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, var_map_index.value(), 0,
+ CodeStubAssembler::INTPTR_PARAMETERS);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSIteratorResult::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
+ assembler->Return(iterator);
+ }
+
+ assembler->Bind(&allocate_typed_array_iterator);
+ {
+ Node* map_index = assembler->IntPtrAdd(
+ assembler->IntPtrConstant(
+ Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX),
+ assembler->Int32Sub(assembler->LoadMapElementsKind(var_map.value()),
+ assembler->Int32Constant(UINT8_ELEMENTS)));
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kIteratedObjectOffset,
+ var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->Return(iterator);
+ }
+}
+
+void Builtins::Generate_ArrayPrototypeKeys(CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Label Label;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Variable var_array(assembler, MachineRepresentation::kTagged);
+ Variable var_result(assembler, MachineRepresentation::kTagged);
+ Variable var_map(assembler, MachineRepresentation::kTagged);
+
+ Label call_to_object(assembler);
+ Label check_instance_type(assembler);
+ Label if_isfastarray(assembler);
+ Label if_isgeneric(assembler);
+ Label allocate_array_iterator(assembler);
+ Label allocate_typed_array_iterator(assembler);
+
+ Node* receiver = assembler->Parameter(0);
+ Node* context = assembler->Parameter(3);
+ Node* native_context = assembler->LoadNativeContext(context);
+
+ var_array.Bind(receiver);
+ var_result.Bind(assembler->UndefinedConstant());
+ var_map.Bind(assembler->UndefinedConstant());
Benedikt Meurer 2016/10/13 05:07:19 You don't need to Bind var_result and var_map here
caitp 2016/10/13 22:32:43 They are, but as I mentioned, they still hit CHECK
+
+ assembler->Branch(assembler->TaggedIsSmi(var_array.value()), &call_to_object,
+ &check_instance_type);
+ assembler->Bind(&check_instance_type);
+ {
+ var_map.Bind(assembler->LoadMap(var_array.value()));
+ Node* instance_type = assembler->LoadMapInstanceType(var_map.value());
+ assembler->GotoIf(
+ assembler->Int32LessThan(
+ instance_type, assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
+ &call_to_object);
+
+ assembler->Branch(
+ assembler->WordEqual(instance_type,
+ assembler->Int32Constant(JS_ARRAY_TYPE)),
+ &allocate_array_iterator, &allocate_typed_array_iterator);
Benedikt Meurer 2016/10/13 05:07:19 You need to handle the generic as well. Also non-f
caitp 2016/10/13 22:32:43 I'm not sure it's possible to skip the length chec
Benedikt Meurer 2016/10/14 03:46:50 What I'm saying is you need to do the map check de
+ }
+
+ assembler->Bind(&call_to_object);
+ {
+ Callable callable = CodeFactory::ToObject(assembler->isolate());
+ Node* result = assembler->CallStub(callable, context, var_array.value());
+ var_array.Bind(result);
+ assembler->Goto(&allocate_array_iterator);
+ }
+
+ assembler->Bind(&allocate_array_iterator);
+ {
+ Node* map_index = assembler->IntPtrConstant(
+ Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX);
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* iterator = assembler->Allocate(JSArrayIterator::kSize);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSIteratorResult::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator, JSIteratorResult::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectOffset, var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSArrayIterator::kIteratedObjectMapOffset, var_map.value());
+ assembler->Return(iterator);
+ }
+
+ assembler->Bind(&allocate_typed_array_iterator);
+ {
+ Node* map_index =
+ assembler->IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
+ Node* map = assembler->LoadFixedArrayElement(
+ native_context, map_index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
+ Node* iterator = assembler->Allocate(JSTypedArrayIterator::kSize);
+ assembler->StoreMapNoWriteBarrier(iterator, map);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kPropertiesOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldRoot(iterator,
+ JSTypedArrayIterator::kElementsOffset,
+ Heap::kEmptyFixedArrayRootIndex);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kIteratedObjectOffset,
+ var_array.value());
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kNextIndexOffset,
+ assembler->SmiConstant(Smi::FromInt(0)));
+ assembler->Return(iterator);
+ }
+}
+
+void Builtins::Generate_ArrayIteratorPrototypeNext(
+ CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Label Label;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Variable var_value(assembler, MachineRepresentation::kTagged);
+ Variable var_done(assembler, MachineRepresentation::kTagged);
+ Variable var_result(assembler, MachineRepresentation::kTagged);
+
+ Label set_done_and_return(assembler);
+ Label did_set_done(assembler);
+ Label allocate_entry_if_needed(assembler);
+ Label allocate_iterator_result(assembler);
+ Label throw_bad_receiver(assembler);
+
+ Label if_isarray(assembler);
+ Label if_istypedarray(assembler);
+ Label if_slow(assembler);
+ Label if_slownotkeyiterator(assembler);
+
+ var_value.Bind(assembler->UndefinedConstant());
+ var_done.Bind(assembler->BooleanConstant(false));
+ var_result.Bind(assembler->UndefinedConstant());
+
+ Node* iterator = assembler->Parameter(0);
+ Node* context = assembler->Parameter(3);
+
+ // 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);
+ // FIXME: Use bitmasks instead of integer ranges
Benedikt Meurer 2016/10/13 05:07:19 You can subtract the base and then do a single uns
caitp 2016/10/13 22:32:43 Done, seems to be working nicely.
+ assembler->GotoIf(
+ assembler->Int32LessThan(
+ instance_type, assembler->Int32Constant(FIRST_ARRAY_ITERATOR_TYPE)),
+ &throw_bad_receiver);
+ assembler->GotoIf(
+ assembler->Int32GreaterThan(
+ instance_type, assembler->Int32Constant(LAST_ARRAY_ITERATOR_TYPE)),
+ &throw_bad_receiver);
+
+ Node* native_context = assembler->LoadNativeContext(context);
+
+ // Let a be O.[[IteratedObject]].
+ STATIC_ASSERT(JSArrayIterator::kIteratedObjectOffset ==
+ JSTypedArrayIterator::kIteratedObjectOffset);
+ Node* array = assembler->LoadObjectField(
+ iterator, JSArrayIterator::kIteratedObjectOffset);
+
+ Node* array_map = assembler->LoadMap(array);
+ Node* array_type = assembler->LoadMapInstanceType(array_map);
+
+ // If a is undefined, return CreateIterResultObject(undefined, true)
+ assembler->GotoIf(assembler->WordEqual(array, assembler->UndefinedConstant()),
+ &did_set_done);
+
+ // Let index be O.[[ArrayIteratorNextIndex]].
+ STATIC_ASSERT(JSArrayIterator::kNextIndexOffset ==
+ JSTypedArrayIterator::kNextIndexOffset);
+ Node* index =
+ assembler->LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset);
+
+ assembler->GotoIf(assembler->Word32Equal(
Benedikt Meurer 2016/10/13 05:07:19 How about just having a single switch over all rel
caitp 2016/10/13 22:32:43 Done
+ array_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
+ &if_isarray);
+
+ assembler->Branch(
+ assembler->Word32Equal(array_type,
+ assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+ &if_istypedarray, &if_slow);
+
+ assembler->Bind(&if_isarray);
+ { // JSArray-specialized algorithm for fast JSArrays
Benedikt Meurer 2016/10/13 05:07:19 You can only take the fast JSArray case if the arr
caitp 2016/10/13 22:32:43 I'll add some new interesting tests to ensure all
+ assembler->Assert(assembler->TaggedIsSmi(index));
+
+ Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset);
+ assembler->GotoIf(assembler->SmiAboveOrEqual(index, length),
+ &set_done_and_return);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSStringIterator::kNextIndexOffset,
+ assembler->SmiAdd(index, assembler->SmiConstant(Smi::FromInt(1))));
+
+ Label if_keyiterator(assembler), if_notkeyiterator(assembler);
+
+ assembler->Branch(
+ assembler->WordEqual(
+ instance_type,
+ assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
+ &if_keyiterator, &if_notkeyiterator);
+
+ assembler->Bind(&if_keyiterator);
+ {
+ var_value.Bind(index);
+ assembler->Goto(&allocate_iterator_result);
+ }
+
+ assembler->Bind(&if_notkeyiterator);
+ {
+ assembler->GotoIf(
+ assembler->WordEqual(instance_type,
+ assembler->Int32Constant(
+ JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE)),
+ &if_slow);
+ assembler->GotoIf(
+ assembler->WordEqual(
+ instance_type,
+ assembler->Int32Constant(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE)),
+ &if_slownotkeyiterator);
+ Node* orig_map = assembler->LoadObjectField(
+ iterator, JSArrayIterator::kIteratedObjectMapOffset);
+ assembler->GotoIf(assembler->WordNotEqual(orig_map, array_map),
+ &if_slownotkeyiterator);
+
+ Node* elements = assembler->LoadElements(array);
+ static int32_t kInstanceType[] = {
+ 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 if_smiorobjects(assembler), if_doubles(assembler);
+ Label* instance_type_handlers[] = {
+ &if_smiorobjects, &if_smiorobjects, &if_smiorobjects,
+ &if_smiorobjects, &if_doubles, &if_doubles,
+ &if_smiorobjects, &if_smiorobjects, &if_smiorobjects,
+ &if_smiorobjects, &if_doubles, &if_doubles};
+
+ assembler->Switch(instance_type, &set_done_and_return, kInstanceType,
+ instance_type_handlers, arraysize(kInstanceType));
+
+ assembler->Bind(&if_smiorobjects);
+ {
+ Node* value = assembler->LoadFixedArrayElement(
+ elements, index, 0, CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->UndefinedConstant());
+ assembler->GotoIf(
+ assembler->WordEqual(value, assembler->TheHoleConstant()),
+ &allocate_entry_if_needed);
+ var_value.Bind(value);
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+
+ assembler->Bind(&if_doubles);
+ {
+ 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_istypedarray);
+ { // Special-cased algorithm for JSTypedArrays
+ assembler->Assert(assembler->TaggedIsSmi(index));
+
+ Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset);
+ assembler->GotoIf(assembler->SmiAboveOrEqual(index, length),
+ &set_done_and_return);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSStringIterator::kNextIndexOffset,
+ assembler->SmiAdd(index, assembler->SmiConstant(Smi::FromInt(1))));
+
+ Label if_keyiterator(assembler), if_notkeyiterator(assembler);
+
+ assembler->Branch(assembler->WordEqual(
+ instance_type, assembler->Int32Constant(
+ JS_TYPED_ARRAY_KEY_ITERATOR_TYPE)),
+ &if_keyiterator, &if_notkeyiterator);
+
+ assembler->Bind(&if_keyiterator);
+ {
+ var_value.Bind(index);
+ assembler->Goto(&allocate_iterator_result);
+ }
+
+ assembler->Bind(&if_notkeyiterator);
+ {
+ Node* elements = assembler->LoadElements(array);
+ Node* base_pointer = assembler->LoadObjectField(
+ elements, FixedTypedArrayBase::kBasePointerOffset);
+ Node* external_pointer = assembler->LoadObjectField(
+ elements, FixedTypedArrayBase::kExternalPointerOffset);
+ Node* data_pointer = assembler->IntPtrAdd(base_pointer, external_pointer);
+
+ static int32_t kInstanceType[] = {
+ JS_UINT8_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_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
+
+ JS_UINT8_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,
+ JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
+ };
+
+ Label if_uint8(assembler), if_int8(assembler), if_uint16(assembler),
+ if_int16(assembler), if_uint32(assembler), if_int32(assembler),
+ if_float32(assembler), if_float64(assembler);
+ Label* instance_type_handlers[] = {
+ &if_uint8, &if_int8, &if_uint16, &if_int16, &if_uint32,
+ &if_int32, &if_float32, &if_float64, &if_uint8, &if_uint8,
+ &if_int8, &if_uint16, &if_int16, &if_uint32, &if_int32,
+ &if_float32, &if_float64, &if_uint8};
+
+ assembler->Switch(instance_type, &set_done_and_return, kInstanceType,
+ instance_type_handlers, arraysize(kInstanceType));
+
+ assembler->Bind(&if_uint8);
+ {
+ Node* value_uint8 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, UINT8_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->SmiFromWord(value_uint8));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_int8);
+ {
+ Node* value_int8 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, INT8_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->SmiFromWord(value_int8));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_uint16);
+ {
+ Node* value_uint16 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, UINT16_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->SmiFromWord(value_uint16));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_int16);
+ {
+ Node* value_int16 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, INT16_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->SmiFromWord(value_int16));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_uint32);
+ {
+ Node* value_uint32 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, UINT32_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->ChangeUint32ToTagged(value_uint32));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_int32);
+ {
+ Node* value_int32 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, INT32_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->ChangeInt32ToTagged(value_int32));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_float32);
+ {
+ Node* value_float32 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, FLOAT32_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->AllocateHeapNumberWithValue(
+ assembler->ChangeFloat32ToFloat64(value_float32)));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ assembler->Bind(&if_float64);
+ {
+ Node* value_float64 = assembler->LoadFixedTypedArrayElement(
+ data_pointer, index, FLOAT64_ELEMENTS,
+ CodeStubAssembler::SMI_PARAMETERS);
+ var_value.Bind(assembler->AllocateHeapNumberWithValue(value_float64));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ }
+ }
+
+ assembler->Bind(&if_slow);
+ { // Generic objects
+ Label if_slowkeyiterator(assembler);
+ // Let len be ? ToLength(? Get(a, "length")).
+ Node* length;
+ {
+ Callable get_property = CodeFactory::GetProperty(assembler->isolate());
+ length = assembler->CallStub(
+ get_property, context, array,
+ assembler->HeapConstant(
+ assembler->isolate()->factory()->length_string()));
+ Callable to_length = CodeFactory::ToLength(assembler->isolate());
+ length = assembler->CallStub(to_length, context, length);
+ }
+
+ // If index ≥ len, then <goto set_done_and_return>
+ {
+ Label if_notdone(assembler), if_smi(assembler), if_heapnum(assembler);
+
+ assembler->Branch(assembler->TaggedIsSmi(length), &if_smi, &if_heapnum);
+
+ assembler->Bind(&if_smi);
+ {
+ // Are these shortcuts valid?
+ assembler->GotoUnless(assembler->TaggedIsSmi(index),
+ &set_done_and_return);
+ assembler->Branch(assembler->SmiBelow(index, length), &if_notdone,
+ &set_done_and_return);
+ }
+
+ assembler->Bind(&if_heapnum);
+ {
+ // Are these shortcuts valid?
+ assembler->GotoIf(assembler->TaggedIsSmi(index), &if_notdone);
+ assembler->Branch(
+ assembler->Float64LessThan(assembler->LoadHeapNumberValue(index),
+ assembler->LoadHeapNumberValue(length)),
+ &if_notdone, &set_done_and_return);
+ }
+
+ assembler->Bind(&if_notdone);
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSStringIterator::kNextIndexOffset,
+ assembler->NumberInc(index));
+
+ assembler->Branch(
+ assembler->WordEqual(
+ instance_type,
+ assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
+ &if_slowkeyiterator, &if_slownotkeyiterator);
+ }
+
+ assembler->Bind(&if_slowkeyiterator);
+ {
+ var_value.Bind(index);
+ assembler->Goto(&allocate_iterator_result);
+ }
+
+ assembler->Bind(&if_slownotkeyiterator);
+ {
+ Callable callable = CodeFactory::GetProperty(assembler->isolate());
+ var_value.Bind(assembler->CallStub(callable, context, array, index));
+ assembler->Goto(&allocate_entry_if_needed);
+ }
+ }
+
+ assembler->Bind(&set_done_and_return);
+ {
+ assembler->StoreObjectFieldNoWriteBarrier(
+ iterator, JSTypedArrayIterator::kIteratedObjectOffset,
+ assembler->UndefinedConstant());
+ assembler->Goto(&did_set_done);
+ assembler->Bind(&did_set_done);
+ {
+ var_value.Bind(assembler->UndefinedConstant());
+ var_done.Bind(assembler->TrueConstant());
+ 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->LoadFixedArrayElement(
+ native_context,
+ assembler->IntPtrConstant(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX), 0,
+ CodeStubAssembler::INTPTR_PARAMETERS);
+
+ 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->LoadFixedArrayElement(
+ native_context,
+ assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
+ CodeStubAssembler::INTPTR_PARAMETERS);
+ 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 or JSTypedArrayIterator.
+ 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
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/isolate.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698