5 #include "src/builtins/builtins-array-gen.h" 7 #include "src/builtins/builtins-iterator-gen.h" 8 #include "src/builtins/builtins-string-gen.h" 9 #include "src/builtins/builtins-typed-array-gen.h" 10 #include "src/builtins/builtins-utils-gen.h" 11 #include "src/builtins/builtins.h" 12 #include "src/code-stub-assembler.h" 13 #include "src/frame-constants.h" 14 #include "src/heap/factory-inl.h" 15 #include "src/objects/arguments-inl.h" 20 using Node = compiler::Node;
21 using IteratorRecord = IteratorBuiltinsFromDSLAssembler::IteratorRecord;
23 ArrayBuiltinsAssembler::ArrayBuiltinsAssembler(
24 compiler::CodeAssemblerState* state)
25 : CodeStubAssembler(state),
26 k_(this, MachineRepresentation::kTagged),
27 a_(this, MachineRepresentation::kTagged),
28 to_(this, MachineRepresentation::kTagged, SmiConstant(0)),
29 fully_spec_compliant_(this, {&k_, &a_, &to_}) {}
31 void ArrayBuiltinsAssembler::FindResultGenerator() {
32 a_.Bind(UndefinedConstant());
35 Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
36 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
37 this_arg(), k_value, k, o());
38 Label false_continue(
this), return_true(
this);
39 BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
41 ReturnFromBuiltin(k_value);
42 BIND(&false_continue);
46 void ArrayBuiltinsAssembler::FindIndexResultGenerator() {
47 a_.Bind(SmiConstant(-1));
50 Node* ArrayBuiltinsAssembler::FindIndexProcessor(Node* k_value, Node* k) {
51 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
52 this_arg(), k_value, k, o());
53 Label false_continue(
this), return_true(
this);
54 BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
57 BIND(&false_continue);
61 void ArrayBuiltinsAssembler::ForEachResultGenerator() {
62 a_.Bind(UndefinedConstant());
65 Node* ArrayBuiltinsAssembler::ForEachProcessor(Node* k_value, Node* k) {
66 CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
71 void ArrayBuiltinsAssembler::SomeResultGenerator() {
72 a_.Bind(FalseConstant());
75 Node* ArrayBuiltinsAssembler::SomeProcessor(Node* k_value, Node* k) {
76 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
77 this_arg(), k_value, k, o());
78 Label false_continue(
this), return_true(
this);
79 BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
81 ReturnFromBuiltin(TrueConstant());
82 BIND(&false_continue);
86 void ArrayBuiltinsAssembler::EveryResultGenerator() {
87 a_.Bind(TrueConstant());
90 Node* ArrayBuiltinsAssembler::EveryProcessor(Node* k_value, Node* k) {
91 Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
92 this_arg(), k_value, k, o());
93 Label true_continue(
this), return_false(
this);
94 BranchIfToBooleanIsTrue(value, &true_continue, &return_false);
96 ReturnFromBuiltin(FalseConstant());
101 void ArrayBuiltinsAssembler::ReduceResultGenerator() {
102 return a_.Bind(this_arg());
105 Node* ArrayBuiltinsAssembler::ReduceProcessor(Node* k_value, Node* k) {
106 VARIABLE(result, MachineRepresentation::kTagged);
107 Label done(
this, {&result}), initial(
this);
108 GotoIf(WordEqual(a(), TheHoleConstant()), &initial);
109 result.Bind(CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
110 UndefinedConstant(), a(), k_value, k, o()));
114 result.Bind(k_value);
118 return result.value();
121 void ArrayBuiltinsAssembler::ReducePostLoopAction() {
123 GotoIf(WordNotEqual(a(), TheHoleConstant()), &ok);
124 ThrowTypeError(context(), MessageTemplate::kReduceNoInitial);
128 void ArrayBuiltinsAssembler::FilterResultGenerator() {
132 GenerateArraySpeciesCreate();
135 Node* ArrayBuiltinsAssembler::FilterProcessor(Node* k_value, Node* k) {
137 Node* selected = CallJS(CodeFactory::Call(isolate()), context(),
138 callbackfn(), this_arg(), k_value, k, o());
139 Label true_continue(
this, &to_), false_continue(
this);
140 BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue);
141 BIND(&true_continue);
144 Label after_work(
this, &to_);
145 Node* kind =
nullptr;
150 Label object_push_pre(
this), object_push(
this), double_push(
this);
151 BranchIfFastJSArray(CAST(a()), context(), &fast, &runtime);
155 GotoIf(WordNotEqual(LoadJSArrayLength(a()), to_.value()), &runtime);
156 kind = EnsureArrayPushable(LoadMap(a()), &runtime);
157 GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
160 BuildAppendJSArray(HOLEY_SMI_ELEMENTS, a(), k_value, &runtime);
164 BIND(&object_push_pre);
166 Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
172 BuildAppendJSArray(HOLEY_ELEMENTS, a(), k_value, &runtime);
178 BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, a(), k_value, &runtime);
185 CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
193 to_.Bind(NumberInc(to_.value()));
194 Goto(&false_continue);
197 BIND(&false_continue);
201 void ArrayBuiltinsAssembler::MapResultGenerator() {
202 GenerateArraySpeciesCreate(len_);
205 void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() {
207 TNode<JSTypedArray> original_array = CAST(o());
208 TNode<Smi> length = CAST(len_);
209 const char* method_name =
"%TypedArray%.prototype.map";
211 TypedArrayBuiltinsAssembler typedarray_asm(state());
212 TNode<JSTypedArray> a = typedarray_asm.TypedArraySpeciesCreateByLength(
213 context(), original_array, length, method_name);
216 CSA_ASSERT(
this, SmiLessThanOrEqual(CAST(len_), LoadJSTypedArrayLength(a)));
217 fast_typed_array_target_ =
218 Word32Equal(LoadInstanceType(LoadElements(original_array)),
219 LoadInstanceType(LoadElements(a)));
223 Node* ArrayBuiltinsAssembler::SpecCompliantMapProcessor(Node* k_value,
228 Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
229 callbackfn(), this_arg(), k_value, k, o());
232 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mapped_value);
236 Node* ArrayBuiltinsAssembler::FastMapProcessor(Node* k_value, Node* k) {
240 Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
241 callbackfn(), this_arg(), k_value, k, o());
244 ParameterMode mode = SMI_PARAMETERS;
245 Label runtime(
this), finished(
this);
246 Label transition_pre(
this), transition_smi_fast(
this),
247 transition_smi_double(
this);
248 Label array_not_smi(
this), array_fast(
this), array_double(
this);
250 TNode<Int32T> kind = LoadElementsKind(a());
251 Node* elements = LoadElements(a());
252 GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), &array_not_smi);
253 TryStoreArrayElement(HOLEY_SMI_ELEMENTS, mode, &transition_pre, elements, k,
257 BIND(&transition_pre);
260 CSA_ASSERT(
this, TaggedIsNotSmi(mapped_value));
261 GotoIf(IsHeapNumberMap(LoadMap(mapped_value)), &transition_smi_double);
262 Goto(&transition_smi_fast);
265 BIND(&array_not_smi);
267 Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &array_double,
271 BIND(&transition_smi_fast);
274 Node*
const native_context = LoadNativeContext(context());
275 Node*
const fast_map = LoadContextElement(
276 native_context, Context::JS_ARRAY_HOLEY_ELEMENTS_MAP_INDEX);
281 StoreMap(a(), fast_map);
287 TryStoreArrayElement(HOLEY_ELEMENTS, mode, &runtime, elements, k,
292 BIND(&transition_smi_double);
295 Node*
const native_context = LoadNativeContext(context());
296 Node*
const double_map = LoadContextElement(
297 native_context, Context::JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX);
299 const ElementsKind kFromKind = HOLEY_SMI_ELEMENTS;
300 const ElementsKind kToKind = HOLEY_DOUBLE_ELEMENTS;
302 Label transition_in_runtime(
this, Label::kDeferred);
303 TransitionElementsKind(a(), double_map, kFromKind, kToKind,
304 &transition_in_runtime);
307 BIND(&transition_in_runtime);
308 CallRuntime(Runtime::kTransitionElementsKind, context(), a(), double_map);
317 elements = LoadElements(a());
320 TryStoreArrayElement(HOLEY_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
328 CallRuntime(Runtime::kCreateDataProperty, context(), a(), k,
338 Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) {
340 Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
341 callbackfn(), this_arg(), k_value, k, o());
342 Label fast(
this), slow(
this), done(
this), detached(
this, Label::kDeferred);
348 Branch(fast_typed_array_target_, &fast, &slow);
356 if (source_elements_kind_ == BIGINT64_ELEMENTS ||
357 source_elements_kind_ == BIGUINT64_ELEMENTS) {
358 num_value = ToBigInt(context(), mapped_value);
360 num_value = ToNumber_Inline(context(), mapped_value);
363 EmitElementStore(a(), k, num_value, source_elements_kind_,
364 KeyedAccessStoreMode::STANDARD_STORE, &detached,
369 SetPropertyStrict(context(), CAST(a()), CAST(k), CAST(mapped_value));
375 ThrowTypeError(context_, MessageTemplate::kDetachedOperation, name_);
381 void ArrayBuiltinsAssembler::NullPostLoopAction() {}
383 void ArrayBuiltinsAssembler::FillFixedArrayWithSmiZero(
384 TNode<FixedArray> array, TNode<Smi> smi_length) {
385 CSA_ASSERT(
this, Word32BinaryNot(IsFixedDoubleArray(array)));
387 TNode<IntPtrT> length = SmiToIntPtr(smi_length);
388 TNode<WordT> byte_length = TimesPointerSize(length);
389 CSA_ASSERT(
this, UintPtrLessThan(length, byte_length));
391 static const int32_t fa_base_data_offset =
392 FixedArray::kHeaderSize - kHeapObjectTag;
393 TNode<IntPtrT> backing_store = IntPtrAdd(
394 BitcastTaggedToWord(array), IntPtrConstant(fa_base_data_offset));
397 TNode<ExternalReference> memset =
398 ExternalConstant(ExternalReference::libc_memset_function());
399 STATIC_ASSERT(kSizetSize == kIntptrSize);
400 CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
401 MachineType::IntPtr(), MachineType::UintPtr(), memset,
402 backing_store, IntPtrConstant(0), byte_length);
405 void ArrayBuiltinsAssembler::ReturnFromBuiltin(Node* value) {
406 if (argc_ ==
nullptr) {
411 PopAndReturn(IntPtrAdd(argc_, IntPtrConstant(1)), value);
415 void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinBody(
416 TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
417 Node* this_arg, TNode<IntPtrT> argc) {
419 receiver_ = receiver;
420 callbackfn_ = callbackfn;
421 this_arg_ = this_arg;
425 void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinBody(
426 const char* name,
const BuiltinResultGenerator& generator,
427 const CallResultProcessor& processor,
const PostLoopAction& action,
428 const Callable& slow_case_continuation,
429 MissingPropertyMode missing_property_mode, ForEachDirection direction) {
430 Label non_array(
this), array_changes(
this, {&k_, &a_, &to_});
434 Label throw_null_undefined_exception(
this, Label::kDeferred);
435 GotoIf(IsNullOrUndefined(receiver()), &throw_null_undefined_exception);
441 o_ = ToObject_Inline(context(), receiver());
445 TVARIABLE(Number, merged_length);
446 Label has_length(
this, &merged_length), not_js_array(
this);
447 GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), ¬_js_array);
448 merged_length = LoadJSArrayLength(CAST(o()));
454 GetProperty(context(), o(), isolate()->factory()->length_string());
455 merged_length = ToLength_Inline(context(), len_property);
460 len_ = merged_length.value();
463 Label type_exception(
this, Label::kDeferred);
465 GotoIf(TaggedIsSmi(callbackfn()), &type_exception);
466 Branch(IsCallableMap(LoadMap(callbackfn())), &done, &type_exception);
468 BIND(&throw_null_undefined_exception);
469 ThrowTypeError(context(), MessageTemplate::kCalledOnNullOrUndefined,
472 BIND(&type_exception);
473 ThrowTypeError(context(), MessageTemplate::kCalledNonCallable,
482 if (direction == ForEachDirection::kForward) {
484 k_.Bind(SmiConstant(0));
486 k_.Bind(NumberDec(len()));
491 HandleFastElements(processor, action, &fully_spec_compliant_, direction,
492 missing_property_mode);
494 BIND(&fully_spec_compliant_);
497 CallStub(slow_case_continuation, context(), receiver(), callbackfn(),
498 this_arg(), a_.value(), o(), k_.value(), len(), to_.value());
499 ReturnFromBuiltin(result);
502 void ArrayBuiltinsAssembler::InitIteratingArrayBuiltinLoopContinuation(
503 TNode<Context> context, TNode<Object> receiver, Node* callbackfn,
504 Node* this_arg, Node* a, TNode<JSReceiver> o, Node* initial_k,
505 TNode<Number> len, Node* to) {
507 this_arg_ = this_arg;
508 callbackfn_ = callbackfn;
516 void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody(
517 const char* name,
const BuiltinResultGenerator& generator,
518 const CallResultProcessor& processor,
const PostLoopAction& action,
519 ForEachDirection direction) {
524 Label throw_not_typed_array(
this, Label::kDeferred);
526 GotoIf(TaggedIsSmi(receiver_), &throw_not_typed_array);
527 GotoIfNot(HasInstanceType(CAST(receiver_), JS_TYPED_ARRAY_TYPE),
528 &throw_not_typed_array);
530 TNode<JSTypedArray> typed_array = CAST(receiver_);
533 TNode<JSArrayBuffer> array_buffer =
534 LoadJSArrayBufferViewBuffer(typed_array);
535 ThrowIfArrayBufferIsDetached(context_, array_buffer, name_);
537 len_ = LoadJSTypedArrayLength(typed_array);
539 Label throw_not_callable(
this, Label::kDeferred);
540 Label distinguish_types(
this);
541 GotoIf(TaggedIsSmi(callbackfn_), &throw_not_callable);
542 Branch(IsCallableMap(LoadMap(callbackfn_)), &distinguish_types,
543 &throw_not_callable);
545 BIND(&throw_not_typed_array);
546 ThrowTypeError(context_, MessageTemplate::kNotTypedArray);
548 BIND(&throw_not_callable);
549 ThrowTypeError(context_, MessageTemplate::kCalledNonCallable, callbackfn_);
551 Label unexpected_instance_type(
this);
552 BIND(&unexpected_instance_type);
555 std::vector<int32_t> instance_types = {
556 #define INSTANCE_TYPE(Type, type, TYPE, ctype) FIXED_##TYPE##_ARRAY_TYPE, 557 TYPED_ARRAYS(INSTANCE_TYPE)
560 std::vector<Label> labels;
561 for (
size_t i = 0;
i < instance_types.size(); ++
i) {
562 labels.push_back(Label(
this));
564 std::vector<Label*> label_ptrs;
565 for (Label& label : labels) {
566 label_ptrs.push_back(&label);
569 BIND(&distinguish_types);
573 if (direction == ForEachDirection::kForward) {
574 k_.Bind(SmiConstant(0));
576 k_.Bind(NumberDec(len()));
578 CSA_ASSERT(
this, IsSafeInteger(k()));
579 Node* instance_type = LoadInstanceType(LoadElements(typed_array));
580 Switch(instance_type, &unexpected_instance_type, instance_types.data(),
581 label_ptrs.data(), labels.size());
583 for (
size_t i = 0;
i < labels.size(); ++
i) {
586 source_elements_kind_ = ElementsKindForInstanceType(
587 static_cast<InstanceType>(instance_types[
i]));
591 VisitAllTypedArrayElements(array_buffer, processor, &done, direction,
597 ReturnFromBuiltin(a_.value());
601 void ArrayBuiltinsAssembler::GenerateIteratingArrayBuiltinLoopContinuation(
602 const CallResultProcessor& processor,
const PostLoopAction& action,
603 MissingPropertyMode missing_property_mode, ForEachDirection direction) {
604 Label loop(
this, {&k_, &a_, &to_});
605 Label after_loop(
this);
609 if (direction == ForEachDirection::kForward) {
611 GotoIfNumberGreaterThanOrEqual(k(), len_, &after_loop);
615 GotoIfNumberGreaterThanOrEqual(SmiConstant(-1), k(), &after_loop);
618 Label done_element(
this, &to_);
622 CSA_ASSERT(
this, IsSafeInteger(k()));
624 if (missing_property_mode == MissingPropertyMode::kSkip) {
627 TNode<Oddball> k_present =
628 HasProperty(context(), o(), k(), kHasProperty);
631 GotoIf(IsFalse(k_present), &done_element);
636 Node* k_value = GetProperty(context(), o(), k());
640 a_.Bind(processor(
this, k_value, k()));
645 if (direction == ForEachDirection::kForward) {
647 k_.Bind(NumberInc(k()));
650 k_.Bind(NumberDec(k()));
660 ElementsKind ArrayBuiltinsAssembler::ElementsKindForInstanceType(
663 #define INSTANCE_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype) \ 664 case FIXED_##TYPE##_ARRAY_TYPE: \ 665 return TYPE##_ELEMENTS; 667 TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENTS_KIND)
668 #undef INSTANCE_TYPE_TO_ELEMENTS_KIND 675 void ArrayBuiltinsAssembler::VisitAllTypedArrayElements(
676 Node* array_buffer,
const CallResultProcessor& processor, Label* detached,
677 ForEachDirection direction, TNode<JSTypedArray> typed_array) {
678 VariableList list({&a_, &k_, &to_}, zone());
680 FastLoopBody body = [&](Node* index) {
681 GotoIf(IsDetachedBuffer(array_buffer), detached);
682 Node* elements = LoadElements(typed_array);
684 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
686 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
687 MachineType::Pointer());
688 Node* data_ptr = IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
689 Node* value = LoadFixedTypedArrayElementAsTagged(
690 data_ptr, index, source_elements_kind_, SMI_PARAMETERS);
692 a_.Bind(processor(
this, value, index));
694 Node* start = SmiConstant(0);
696 IndexAdvanceMode advance_mode = IndexAdvanceMode::kPost;
698 if (direction == ForEachDirection::kReverse) {
699 std::swap(start, end);
700 advance_mode = IndexAdvanceMode::kPre;
703 BuildFastLoop(list, start, end, body, incr, ParameterMode::SMI_PARAMETERS,
707 void ArrayBuiltinsAssembler::VisitAllFastElementsOneKind(
708 ElementsKind kind,
const CallResultProcessor& processor,
709 Label* array_changed, ParameterMode mode, ForEachDirection direction,
710 MissingPropertyMode missing_property_mode, TNode<Smi> length) {
711 Comment(
"begin VisitAllFastElementsOneKind");
714 CSA_ASSERT(
this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
715 VARIABLE(original_map, MachineRepresentation::kTagged);
716 original_map.Bind(LoadMap(o()));
717 VariableList list({&original_map, &a_, &k_, &to_}, zone());
718 Node* start = IntPtrOrSmiConstant(0, mode);
719 Node* end = TaggedToParameter(length, mode);
720 IndexAdvanceMode advance_mode = direction == ForEachDirection::kReverse
721 ? IndexAdvanceMode::kPre
722 : IndexAdvanceMode::kPost;
723 if (direction == ForEachDirection::kReverse) std::swap(start, end);
726 [=, &original_map](Node* index) {
727 k_.Bind(ParameterToTagged(index, mode));
728 Label one_element_done(
this), hole_element(
this),
729 process_element(
this);
734 Node* o_map = LoadMap(o());
735 GotoIf(WordNotEqual(o_map, original_map.value()), array_changed);
737 TNode<JSArray> o_array = CAST(o());
740 GotoIf(SmiGreaterThanOrEqual(CAST(k_.value()),
741 CAST(LoadJSArrayLength(o_array))),
745 Node* elements = LoadElements(o_array);
749 DCHECK(kind == PACKED_ELEMENTS || kind == PACKED_DOUBLE_ELEMENTS);
750 int base_size = kind == PACKED_ELEMENTS
751 ? FixedArray::kHeaderSize
752 : (FixedArray::kHeaderSize - kHeapObjectTag);
753 Node* offset = ElementOffsetFromIndex(index, kind, mode, base_size);
754 VARIABLE(value, MachineRepresentation::kTagged);
755 if (kind == PACKED_ELEMENTS) {
756 value.Bind(LoadObjectField(elements, offset));
757 GotoIf(WordEqual(value.value(), TheHoleConstant()), &hole_element);
760 LoadDoubleWithHoleCheck(elements, offset, &hole_element);
761 value.Bind(AllocateHeapNumberWithValue(double_value));
763 Goto(&process_element);
766 if (missing_property_mode == MissingPropertyMode::kSkip) {
768 Branch(IsNoElementsProtectorCellInvalid(), array_changed,
771 value.Bind(UndefinedConstant());
772 Goto(&process_element);
774 BIND(&process_element);
776 a_.Bind(processor(
this, value.value(), k()));
777 Goto(&one_element_done);
779 BIND(&one_element_done);
781 1, mode, advance_mode);
782 Comment(
"end VisitAllFastElementsOneKind");
785 void ArrayBuiltinsAssembler::HandleFastElements(
786 const CallResultProcessor& processor,
const PostLoopAction& action,
787 Label* slow, ForEachDirection direction,
788 MissingPropertyMode missing_property_mode) {
789 Label switch_on_elements_kind(
this), fast_elements(
this),
790 maybe_double_elements(
this), fast_double_elements(
this);
792 Comment(
"begin HandleFastElements");
794 GotoIf(TaggedIsNotSmi(len()), slow);
796 BranchIfFastJSArray(o(), context(),
797 &switch_on_elements_kind, slow);
799 BIND(&switch_on_elements_kind);
800 TNode<Smi> smi_len = CAST(len());
802 Node* kind = LoadElementsKind(o());
803 Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS),
804 &maybe_double_elements, &fast_elements);
806 ParameterMode mode = OptimalParameterMode();
807 BIND(&fast_elements);
809 VisitAllFastElementsOneKind(PACKED_ELEMENTS, processor, slow, mode,
810 direction, missing_property_mode, smi_len);
815 ReturnFromBuiltin(a_.value());
818 BIND(&maybe_double_elements);
819 Branch(IsElementsKindGreaterThan(kind, HOLEY_DOUBLE_ELEMENTS), slow,
820 &fast_double_elements);
822 BIND(&fast_double_elements);
824 VisitAllFastElementsOneKind(PACKED_DOUBLE_ELEMENTS, processor, slow, mode,
825 direction, missing_property_mode, smi_len);
830 ReturnFromBuiltin(a_.value());
837 void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate() {
838 Label runtime(
this, Label::kDeferred), done(
this);
840 TNode<Smi> len = SmiConstant(0);
841 TNode<Map> original_map = LoadMap(o());
843 InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
846 GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
849 Node* species_protector = ArraySpeciesProtectorConstant();
851 LoadObjectField(species_protector, PropertyCell::kValueOffset);
852 TNode<Smi>
const protector_invalid =
853 SmiConstant(Isolate::kProtectorInvalid);
854 GotoIf(WordEqual(value, protector_invalid), &runtime);
857 TNode<Int32T> elements_kind = LoadMapElementsKind(original_map);
858 GotoIfNot(IsFastElementsKind(elements_kind), &runtime);
859 TNode<Context> native_context = LoadNativeContext(context());
860 TNode<Map> array_map =
861 LoadJSArrayElementsMap(elements_kind, native_context);
862 TNode<JSArray> array =
863 AllocateJSArray(GetInitialFastElementsKind(), array_map, len, len,
864 nullptr, CodeStubAssembler::SMI_PARAMETERS);
872 TNode<JSReceiver> constructor =
873 CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
874 a_.Bind(Construct(context(), constructor, len));
875 Goto(&fully_spec_compliant_);
882 void ArrayBuiltinsAssembler::GenerateArraySpeciesCreate(TNode<Number> len) {
883 Label runtime(
this, Label::kDeferred), done(
this);
885 Node*
const original_map = LoadMap(o());
887 InstanceTypeEqual(LoadMapInstanceType(original_map), JS_ARRAY_TYPE),
890 GotoIfNot(IsPrototypeInitialArrayPrototype(context(), original_map),
893 Node* species_protector = ArraySpeciesProtectorConstant();
895 LoadObjectField(species_protector, PropertyCell::kValueOffset);
896 Node*
const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
897 GotoIf(WordEqual(value, protector_invalid), &runtime);
899 GotoIfNot(TaggedIsPositiveSmi(len), &runtime);
901 IsValidFastJSArrayCapacity(len, CodeStubAssembler::SMI_PARAMETERS),
907 const ElementsKind elements_kind =
908 GetHoleyElementsKind(GetInitialFastElementsKind());
909 TNode<Context> native_context = LoadNativeContext(context());
910 TNode<Map> array_map =
911 LoadJSArrayElementsMap(elements_kind, native_context);
912 a_.Bind(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, len, CAST(len),
913 nullptr, CodeStubAssembler::SMI_PARAMETERS,
914 kAllowLargeObjectAllocation));
921 TNode<JSReceiver> constructor =
922 CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context(), o()));
923 a_.Bind(Construct(context(), constructor, len));
924 Goto(&fully_spec_compliant_);
930 TF_BUILTIN(ArrayPrototypePop, CodeStubAssembler) {
932 UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
933 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
934 CSA_ASSERT(
this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
936 CodeStubArguments args(
this, ChangeInt32ToIntPtr(argc));
937 TNode<Object> receiver = args.GetReceiver();
939 Label runtime(
this, Label::kDeferred);
949 BranchIfFastJSArray(receiver, context, &fast, &runtime);
953 TNode<JSArray> array_receiver = CAST(receiver);
954 CSA_ASSERT(
this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
955 TNode<IntPtrT> length =
956 LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset);
957 Label return_undefined(
this), fast_elements(
this);
958 GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
961 EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
964 TNode<FixedArrayBase> elements = LoadElements(array_receiver);
965 GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)),
968 TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1));
972 TNode<IntPtrT> capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
973 GotoIf(IntPtrLessThan(
974 IntPtrAdd(IntPtrAdd(new_length, new_length),
975 IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
979 StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
982 TNode<Int32T> elements_kind = LoadElementsKind(array_receiver);
983 GotoIf(Int32LessThanOrEqual(elements_kind,
984 Int32Constant(TERMINAL_FAST_ELEMENTS_KIND)),
987 Node* value = LoadFixedDoubleArrayElement(CAST(elements), new_length,
990 StoreFixedDoubleArrayHole(CAST(elements), new_length);
991 args.PopAndReturn(AllocateHeapNumberWithValue(value));
993 BIND(&fast_elements);
995 Node* value = LoadFixedArrayElement(CAST(elements), new_length);
996 StoreFixedArrayElement(CAST(elements), new_length, TheHoleConstant());
997 GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
998 args.PopAndReturn(value);
1001 BIND(&return_undefined);
1002 { args.PopAndReturn(UndefinedConstant()); }
1010 TNode<JSFunction> target = LoadTargetFromFrame();
1011 TailCallBuiltin(Builtins::kArrayPop, context, target, UndefinedConstant(),
1016 TF_BUILTIN(ArrayPrototypePush, CodeStubAssembler) {
1017 TVARIABLE(IntPtrT, arg_index);
1018 Label default_label(
this, &arg_index);
1019 Label smi_transition(
this);
1020 Label object_push_pre(
this);
1021 Label object_push(
this, &arg_index);
1022 Label double_push(
this, &arg_index);
1023 Label double_transition(
this);
1024 Label runtime(
this, Label::kDeferred);
1028 TNode<Int32T> argc =
1029 UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
1030 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1031 CSA_ASSERT(
this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
1033 CodeStubArguments args(
this, ChangeInt32ToIntPtr(argc));
1034 TNode<Object> receiver = args.GetReceiver();
1035 TNode<JSArray> array_receiver;
1036 Node* kind =
nullptr;
1039 BranchIfFastJSArray(receiver, context, &fast, &runtime);
1043 array_receiver = CAST(receiver);
1044 arg_index = IntPtrConstant(0);
1045 kind = EnsureArrayPushable(LoadMap(array_receiver), &runtime);
1046 GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS),
1049 Node* new_length = BuildAppendJSArray(PACKED_SMI_ELEMENTS, array_receiver,
1050 &args, &arg_index, &smi_transition);
1051 args.PopAndReturn(new_length);
1058 BIND(&smi_transition);
1060 Node* arg = args.AtIndex(arg_index.value());
1061 GotoIf(TaggedIsSmi(arg), &default_label);
1062 Node* length = LoadJSArrayLength(array_receiver);
1065 SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
1066 Increment(&arg_index);
1069 Node* kind = LoadElementsKind(array_receiver);
1070 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
1073 GotoIfNotNumber(arg, &object_push);
1077 BIND(&object_push_pre);
1079 Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &double_push,
1085 Node* new_length = BuildAppendJSArray(PACKED_ELEMENTS, array_receiver,
1086 &args, &arg_index, &default_label);
1087 args.PopAndReturn(new_length);
1093 BuildAppendJSArray(PACKED_DOUBLE_ELEMENTS, array_receiver, &args,
1094 &arg_index, &double_transition);
1095 args.PopAndReturn(new_length);
1102 BIND(&double_transition);
1104 Node* arg = args.AtIndex(arg_index.value());
1105 GotoIfNumber(arg, &default_label);
1106 Node* length = LoadJSArrayLength(array_receiver);
1109 SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
1110 Increment(&arg_index);
1113 Node* kind = LoadElementsKind(array_receiver);
1114 GotoIf(Word32Equal(kind, Int32Constant(DICTIONARY_ELEMENTS)),
1121 BIND(&default_label);
1124 [
this, array_receiver, context](Node* arg) {
1125 Node* length = LoadJSArrayLength(array_receiver);
1126 SetPropertyStrict(context, array_receiver, CAST(length), CAST(arg));
1129 args.PopAndReturn(LoadJSArrayLength(array_receiver));
1137 TNode<JSFunction> target = LoadTargetFromFrame();
1138 TailCallBuiltin(Builtins::kArrayPush, context, target, UndefinedConstant(),
1143 TF_BUILTIN(ArrayPrototypeShift, CodeStubAssembler) {
1144 TNode<Int32T> argc =
1145 UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
1146 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1147 CSA_ASSERT(
this, IsUndefined(Parameter(Descriptor::kJSNewTarget)));
1149 CodeStubArguments args(
this, ChangeInt32ToIntPtr(argc));
1150 TNode<Object> receiver = args.GetReceiver();
1152 Label runtime(
this, Label::kDeferred);
1163 BranchIfFastJSArray(receiver, context, &fast, &runtime);
1167 TNode<JSArray> array_receiver = CAST(receiver);
1168 CSA_ASSERT(
this, TaggedIsPositiveSmi(LoadJSArrayLength(array_receiver)));
1175 EnsureArrayLengthWritable(LoadMap(array_receiver), &runtime);
1177 TNode<IntPtrT> length =
1178 LoadAndUntagObjectField(array_receiver, JSArray::kLengthOffset);
1179 Label return_undefined(
this), fast_elements_tagged(
this),
1180 fast_elements_smi(
this);
1181 GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_undefined);
1184 TNode<FixedArrayBase> elements = LoadElements(array_receiver);
1185 GotoIf(WordEqual(LoadMap(elements), LoadRoot(RootIndex::kFixedCOWArrayMap)),
1188 TNode<IntPtrT> new_length = IntPtrSub(length, IntPtrConstant(1));
1192 Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
1193 GotoIf(IntPtrLessThan(
1194 IntPtrAdd(IntPtrAdd(new_length, new_length),
1195 IntPtrConstant(JSObject::kMinAddedElementsCapacity)),
1201 GotoIf(IntPtrGreaterThan(new_length,
1202 IntPtrConstant(JSArray::kMaxCopyElements)),
1205 StoreObjectFieldNoWriteBarrier(array_receiver, JSArray::kLengthOffset,
1206 SmiTag(new_length));
1208 TNode<IntPtrT> element_zero = IntPtrConstant(0);
1209 TNode<IntPtrT> element_one = IntPtrConstant(1);
1210 TNode<Int32T> elements_kind = LoadElementsKind(array_receiver);
1212 Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_SMI_ELEMENTS)),
1213 &fast_elements_smi);
1214 GotoIf(Int32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
1215 &fast_elements_tagged);
1220 Int32LessThanOrEqual(elements_kind,
1221 Int32Constant(HOLEY_DOUBLE_ELEMENTS)));
1223 VARIABLE(result, MachineRepresentation::kTagged, UndefinedConstant());
1225 Label move_elements(
this);
1226 result.Bind(AllocateHeapNumberWithValue(LoadFixedDoubleArrayElement(
1227 CAST(elements), element_zero, &move_elements)));
1228 Goto(&move_elements);
1229 BIND(&move_elements);
1231 MoveElements(HOLEY_DOUBLE_ELEMENTS, elements, element_zero, element_one,
1233 StoreFixedDoubleArrayHole(CAST(elements), new_length);
1234 args.PopAndReturn(result.value());
1237 BIND(&fast_elements_tagged);
1239 TNode<FixedArray> elements_fixed_array = CAST(elements);
1240 Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
1241 MoveElements(HOLEY_ELEMENTS, elements, element_zero, element_one,
1243 StoreFixedArrayElement(elements_fixed_array, new_length,
1245 GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
1246 args.PopAndReturn(value);
1249 BIND(&fast_elements_smi);
1251 TNode<FixedArray> elements_fixed_array = CAST(elements);
1252 Node* value = LoadFixedArrayElement(elements_fixed_array, 0);
1253 MoveElements(HOLEY_SMI_ELEMENTS, elements, element_zero, element_one,
1255 StoreFixedArrayElement(elements_fixed_array, new_length,
1257 GotoIf(WordEqual(value, TheHoleConstant()), &return_undefined);
1258 args.PopAndReturn(value);
1261 BIND(&return_undefined);
1262 { args.PopAndReturn(UndefinedConstant()); }
1270 TNode<JSFunction> target = LoadTargetFromFrame();
1271 TailCallBuiltin(Builtins::kArrayShift, context, target, UndefinedConstant(),
1276 TF_BUILTIN(ExtractFastJSArray, ArrayBuiltinsAssembler) {
1277 ParameterMode mode = OptimalParameterMode();
1278 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1279 Node* array = Parameter(Descriptor::kSource);
1280 Node* begin = TaggedToParameter(Parameter(Descriptor::kBegin), mode);
1281 Node* count = TaggedToParameter(Parameter(Descriptor::kCount), mode);
1283 CSA_ASSERT(
this, IsJSArray(array));
1284 CSA_ASSERT(
this, Word32BinaryNot(IsNoElementsProtectorCellInvalid()));
1286 Return(ExtractFastJSArray(context, array, begin, count, mode));
1289 TF_BUILTIN(CloneFastJSArray, ArrayBuiltinsAssembler) {
1290 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1291 TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
1294 Word32Or(Word32BinaryNot(
1295 IsHoleyFastElementsKind(LoadElementsKind(array))),
1296 Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
1298 ParameterMode mode = OptimalParameterMode();
1299 Return(CloneFastJSArray(context, array, mode));
1309 TF_BUILTIN(CloneFastJSArrayFillingHoles, ArrayBuiltinsAssembler) {
1310 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1311 TNode<JSArray> array = CAST(Parameter(Descriptor::kSource));
1314 Word32Or(Word32BinaryNot(
1315 IsHoleyFastElementsKind(LoadElementsKind(array))),
1316 Word32BinaryNot(IsNoElementsProtectorCellInvalid())));
1318 ParameterMode mode = OptimalParameterMode();
1319 Return(CloneFastJSArray(context, array, mode,
nullptr,
1320 HoleConversionMode::kConvertToUndefined));
1323 TF_BUILTIN(ArrayFindLoopContinuation, ArrayBuiltinsAssembler) {
1324 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1325 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1326 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1327 Node* this_arg = Parameter(Descriptor::kThisArg);
1328 Node* array = Parameter(Descriptor::kArray);
1329 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
1330 Node* initial_k = Parameter(Descriptor::kInitialK);
1331 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1332 Node* to = Parameter(Descriptor::kTo);
1334 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
1335 this_arg, array,
object, initial_k,
1338 GenerateIteratingArrayBuiltinLoopContinuation(
1339 &ArrayBuiltinsAssembler::FindProcessor,
1340 &ArrayBuiltinsAssembler::NullPostLoopAction,
1341 MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
1346 TF_BUILTIN(ArrayFindLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
1347 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1348 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1349 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1350 Node* this_arg = Parameter(Descriptor::kThisArg);
1351 Node* initial_k = Parameter(Descriptor::kInitialK);
1352 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1354 Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
1355 callbackfn, this_arg, UndefinedConstant(), receiver,
1356 initial_k, len, UndefinedConstant()));
1361 TF_BUILTIN(ArrayFindLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
1362 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1363 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1364 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1365 Node* this_arg = Parameter(Descriptor::kThisArg);
1366 Node* initial_k = Parameter(Descriptor::kInitialK);
1367 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1369 Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
1370 callbackfn, this_arg, UndefinedConstant(), receiver,
1371 initial_k, len, UndefinedConstant()));
1377 TF_BUILTIN(ArrayFindLoopAfterCallbackLazyDeoptContinuation,
1378 ArrayBuiltinsAssembler) {
1379 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1380 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1381 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1382 Node* this_arg = Parameter(Descriptor::kThisArg);
1383 Node* initial_k = Parameter(Descriptor::kInitialK);
1384 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1385 Node* found_value = Parameter(Descriptor::kFoundValue);
1386 Node* is_found = Parameter(Descriptor::kIsFound);
1392 Label if_true(
this), if_false(
this);
1393 BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
1395 Return(found_value);
1397 Return(CallBuiltin(Builtins::kArrayFindLoopContinuation, context, receiver,
1398 callbackfn, this_arg, UndefinedConstant(), receiver,
1399 initial_k, len, UndefinedConstant()));
1403 TF_BUILTIN(ArrayPrototypeFind, ArrayBuiltinsAssembler) {
1404 TNode<IntPtrT> argc =
1405 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1406 CodeStubArguments args(
this, argc);
1407 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1408 TNode<Object> receiver = args.GetReceiver();
1409 Node* callbackfn = args.GetOptionalArgumentValue(0);
1410 Node* this_arg = args.GetOptionalArgumentValue(1);
1412 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1414 GenerateIteratingArrayBuiltinBody(
1415 "Array.prototype.find", &ArrayBuiltinsAssembler::FindResultGenerator,
1416 &ArrayBuiltinsAssembler::FindProcessor,
1417 &ArrayBuiltinsAssembler::NullPostLoopAction,
1418 Builtins::CallableFor(isolate(), Builtins::kArrayFindLoopContinuation),
1419 MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
1422 TF_BUILTIN(ArrayFindIndexLoopContinuation, ArrayBuiltinsAssembler) {
1423 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1424 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1425 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1426 Node* this_arg = Parameter(Descriptor::kThisArg);
1427 Node* array = Parameter(Descriptor::kArray);
1428 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
1429 Node* initial_k = Parameter(Descriptor::kInitialK);
1430 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1431 Node* to = Parameter(Descriptor::kTo);
1433 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
1434 this_arg, array,
object, initial_k,
1437 GenerateIteratingArrayBuiltinLoopContinuation(
1438 &ArrayBuiltinsAssembler::FindIndexProcessor,
1439 &ArrayBuiltinsAssembler::NullPostLoopAction,
1440 MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
1443 TF_BUILTIN(ArrayFindIndexLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
1444 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1445 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1446 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1447 Node* this_arg = Parameter(Descriptor::kThisArg);
1448 Node* initial_k = Parameter(Descriptor::kInitialK);
1449 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1451 Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
1452 receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
1453 initial_k, len, UndefinedConstant()));
1456 TF_BUILTIN(ArrayFindIndexLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
1457 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1458 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1459 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1460 Node* this_arg = Parameter(Descriptor::kThisArg);
1461 Node* initial_k = Parameter(Descriptor::kInitialK);
1462 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1464 Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
1465 receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
1466 initial_k, len, UndefinedConstant()));
1469 TF_BUILTIN(ArrayFindIndexLoopAfterCallbackLazyDeoptContinuation,
1470 ArrayBuiltinsAssembler) {
1471 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1472 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1473 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1474 Node* this_arg = Parameter(Descriptor::kThisArg);
1475 Node* initial_k = Parameter(Descriptor::kInitialK);
1476 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1477 Node* found_value = Parameter(Descriptor::kFoundValue);
1478 Node* is_found = Parameter(Descriptor::kIsFound);
1484 Label if_true(
this), if_false(
this);
1485 BranchIfToBooleanIsTrue(is_found, &if_true, &if_false);
1487 Return(found_value);
1489 Return(CallBuiltin(Builtins::kArrayFindIndexLoopContinuation, context,
1490 receiver, callbackfn, this_arg, SmiConstant(-1), receiver,
1491 initial_k, len, UndefinedConstant()));
1495 TF_BUILTIN(ArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
1496 TNode<IntPtrT> argc =
1497 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1498 CodeStubArguments args(
this, argc);
1499 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1500 TNode<Object> receiver = args.GetReceiver();
1501 Node* callbackfn = args.GetOptionalArgumentValue(0);
1502 Node* this_arg = args.GetOptionalArgumentValue(1);
1504 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1506 GenerateIteratingArrayBuiltinBody(
1507 "Array.prototype.findIndex",
1508 &ArrayBuiltinsAssembler::FindIndexResultGenerator,
1509 &ArrayBuiltinsAssembler::FindIndexProcessor,
1510 &ArrayBuiltinsAssembler::NullPostLoopAction,
1511 Builtins::CallableFor(isolate(),
1512 Builtins::kArrayFindIndexLoopContinuation),
1513 MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
1523 TVARIABLE(
Object, array);
1524 Label is_constructor(
this), is_not_constructor(
this), done(
this);
1525 GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
1526 Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
1528 BIND(&is_constructor);
1530 array = Construct(context, CAST(receiver));
1534 BIND(&is_not_constructor);
1536 Label allocate_js_array(
this);
1538 TNode<Map> array_map = CAST(LoadContextElement(
1539 context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
1541 array = AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, SmiConstant(0),
1542 SmiConstant(0),
nullptr,
1543 ParameterMode::SMI_PARAMETERS);
1548 return array.value();
1554 TVARIABLE(
Object, array);
1555 Label is_constructor(
this), is_not_constructor(
this), done(
this);
1556 CSA_ASSERT(
this, IsNumberNormalized(length));
1557 GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
1558 Branch(IsConstructor(CAST(receiver)), &is_constructor, &is_not_constructor);
1560 BIND(&is_constructor);
1562 array = Construct(context, CAST(receiver), length);
1566 BIND(&is_not_constructor);
1568 array = ArrayCreate(context, length);
1573 return array.value();
1581 UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount));
1587 Label fast_iterate(
this), normal_iterate(
this);
1592 GotoIfNot(Word32Equal(argc, Int32Constant(1)), &normal_iterate);
1594 LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
1595 Branch(WordEqual(array_function, receiver), &fast_iterate, &normal_iterate);
1597 BIND(&fast_iterate);
1600 TVARIABLE(
Object, var_fast_result);
1601 iterator_assembler.FastIterableToList(context, items, &var_fast_result,
1603 args.PopAndReturn(var_fast_result.value());
1606 BIND(&normal_iterate);
1607 TNode<Object> map_function = args.GetOptionalArgumentValue(1);
1611 Label no_error(
this), error(
this);
1612 GotoIf(IsUndefined(map_function), &no_error);
1613 GotoIf(TaggedIsSmi(map_function), &error);
1614 Branch(IsCallable(CAST(map_function)), &no_error, &error);
1617 ThrowTypeError(context, MessageTemplate::kCalledNonCallable, map_function);
1622 Label iterable(
this), not_iterable(
this), finished(
this), if_exception(
this);
1624 TNode<Object> this_arg = args.GetOptionalArgumentValue(2);
1627 TNode<JSReceiver> array_like = ToObject_Inline(context, items);
1629 TVARIABLE(Object, array);
1630 TVARIABLE(Number, length);
1633 IteratorBuiltinsAssembler iterator_assembler(state());
1634 Node* iterator_method =
1635 iterator_assembler.GetIteratorMethod(context, array_like);
1636 Branch(IsNullOrUndefined(iterator_method), ¬_iterable, &iterable);
1640 TVARIABLE(Number, index, SmiConstant(0));
1641 TVARIABLE(Object, var_exception);
1642 Label loop(
this, &index), loop_done(
this),
1643 on_exception(
this, Label::kDeferred),
1644 index_overflow(
this, Label::kDeferred);
1648 Label get_method_not_callable(
this, Label::kDeferred), next(
this);
1649 GotoIf(TaggedIsSmi(iterator_method), &get_method_not_callable);
1650 GotoIfNot(IsCallable(CAST(iterator_method)), &get_method_not_callable);
1653 BIND(&get_method_not_callable);
1654 ThrowTypeError(context, MessageTemplate::kCalledNonCallable,
1661 array = ConstructArrayLike(context, receiver);
1665 IteratorRecord iterator_record =
1666 iterator_assembler.GetIterator(context, items, iterator_method);
1668 TNode<Context> native_context = LoadNativeContext(context);
1669 TNode<Object> fast_iterator_result_map =
1670 LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
1677 TNode<Object> next = iterator_assembler.IteratorStep(
1678 context, iterator_record, &loop_done, fast_iterator_result_map);
1679 TVARIABLE(Object, value,
1680 CAST(iterator_assembler.IteratorValue(
1681 context, next, fast_iterator_result_map)));
1688 GotoIf(IsUndefined(map_function), &next);
1690 CSA_ASSERT(
this, IsCallable(CAST(map_function)));
1691 Node* v = CallJS(CodeFactory::Call(isolate()), context, map_function,
1692 this_arg, value.value(), index.value());
1693 GotoIfException(v, &on_exception, &var_exception);
1701 Node* define_status =
1702 CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
1703 index.value(), value.value());
1704 GotoIfException(define_status, &on_exception, &var_exception);
1706 index = NumberInc(index.value());
1714 CSA_ASSERT_BRANCH(
this, [&](Label* ok, Label* not_ok) {
1715 BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
1716 NumberConstant(kMaxSafeInteger), ok,
1728 BIND(&on_exception);
1732 iterator_assembler.IteratorCloseOnException(context, iterator_record,
1733 var_exception.value());
1737 BIND(¬_iterable);
1740 length = ToLength_Inline(
1741 context, GetProperty(context, array_like, factory()->length_string()));
1745 array = ConstructArrayLike(context, receiver, length.value());
1747 TVARIABLE(Number, index, SmiConstant(0));
1750 GotoIf(WordEqual<Object, Object>(length.value(), SmiConstant(0)),
1755 Label loop(
this, &index);
1758 TVARIABLE(Object, value);
1760 value = GetProperty(context, array_like, index.value());
1766 GotoIf(IsUndefined(map_function), &next);
1768 CSA_ASSERT(
this, IsCallable(CAST(map_function)));
1769 value = CAST(CallJS(CodeFactory::Call(isolate()), context, map_function,
1770 this_arg, value.value(), index.value()));
1776 CallRuntime(Runtime::kCreateDataProperty, context, array.value(),
1777 index.value(), value.value());
1778 index = NumberInc(index.value());
1779 BranchIfNumberRelationalComparison(Operation::kLessThan, index.value(),
1780 length.value(), &loop, &finished);
1787 SetPropertyLength(context, array.value(), length.value());
1788 args.PopAndReturn(array.value());
1792 TF_BUILTIN(TypedArrayPrototypeFind, ArrayBuiltinsAssembler) {
1793 TNode<IntPtrT> argc =
1794 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1795 CodeStubArguments args(
this, argc);
1796 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1797 TNode<Object> receiver = args.GetReceiver();
1798 Node* callbackfn = args.GetOptionalArgumentValue(0);
1799 Node* this_arg = args.GetOptionalArgumentValue(1);
1801 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1803 GenerateIteratingTypedArrayBuiltinBody(
1804 "%TypedArray%.prototype.find",
1805 &ArrayBuiltinsAssembler::FindResultGenerator,
1806 &ArrayBuiltinsAssembler::FindProcessor,
1807 &ArrayBuiltinsAssembler::NullPostLoopAction);
1811 TF_BUILTIN(TypedArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
1812 TNode<IntPtrT> argc =
1813 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1814 CodeStubArguments args(
this, argc);
1815 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1816 TNode<Object> receiver = args.GetReceiver();
1817 Node* callbackfn = args.GetOptionalArgumentValue(0);
1818 Node* this_arg = args.GetOptionalArgumentValue(1);
1820 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1822 GenerateIteratingTypedArrayBuiltinBody(
1823 "%TypedArray%.prototype.findIndex",
1824 &ArrayBuiltinsAssembler::FindIndexResultGenerator,
1825 &ArrayBuiltinsAssembler::FindIndexProcessor,
1826 &ArrayBuiltinsAssembler::NullPostLoopAction);
1829 TF_BUILTIN(TypedArrayPrototypeForEach, ArrayBuiltinsAssembler) {
1830 TNode<IntPtrT> argc =
1831 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1832 CodeStubArguments args(
this, argc);
1833 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1834 TNode<Object> receiver = args.GetReceiver();
1835 Node* callbackfn = args.GetOptionalArgumentValue(0);
1836 Node* this_arg = args.GetOptionalArgumentValue(1);
1838 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1840 GenerateIteratingTypedArrayBuiltinBody(
1841 "%TypedArray%.prototype.forEach",
1842 &ArrayBuiltinsAssembler::ForEachResultGenerator,
1843 &ArrayBuiltinsAssembler::ForEachProcessor,
1844 &ArrayBuiltinsAssembler::NullPostLoopAction);
1847 TF_BUILTIN(ArraySomeLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
1848 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1849 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1850 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1851 Node* this_arg = Parameter(Descriptor::kThisArg);
1852 Node* initial_k = Parameter(Descriptor::kInitialK);
1853 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1854 Node* result = Parameter(Descriptor::kResult);
1859 Label true_continue(
this), false_continue(
this);
1862 BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
1863 BIND(&true_continue);
1864 { Return(TrueConstant()); }
1865 BIND(&false_continue);
1868 initial_k = NumberInc(initial_k);
1870 Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
1871 callbackfn, this_arg, FalseConstant(), receiver,
1872 initial_k, len, UndefinedConstant()));
1876 TF_BUILTIN(ArraySomeLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
1877 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1878 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1879 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1880 Node* this_arg = Parameter(Descriptor::kThisArg);
1881 Node* initial_k = Parameter(Descriptor::kInitialK);
1882 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1884 Return(CallBuiltin(Builtins::kArraySomeLoopContinuation, context, receiver,
1885 callbackfn, this_arg, FalseConstant(), receiver, initial_k,
1886 len, UndefinedConstant()));
1889 TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinsAssembler) {
1890 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1891 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1892 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1893 Node* this_arg = Parameter(Descriptor::kThisArg);
1894 Node* array = Parameter(Descriptor::kArray);
1895 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
1896 Node* initial_k = Parameter(Descriptor::kInitialK);
1897 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1898 Node* to = Parameter(Descriptor::kTo);
1900 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
1901 this_arg, array,
object, initial_k,
1904 GenerateIteratingArrayBuiltinLoopContinuation(
1905 &ArrayBuiltinsAssembler::SomeProcessor,
1906 &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
1909 TF_BUILTIN(ArraySome, ArrayBuiltinsAssembler) {
1910 TNode<IntPtrT> argc =
1911 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1912 CodeStubArguments args(
this, argc);
1913 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1914 TNode<Object> receiver = args.GetReceiver();
1915 Node* callbackfn = args.GetOptionalArgumentValue(0);
1916 Node* this_arg = args.GetOptionalArgumentValue(1);
1918 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1920 GenerateIteratingArrayBuiltinBody(
1921 "Array.prototype.some", &ArrayBuiltinsAssembler::SomeResultGenerator,
1922 &ArrayBuiltinsAssembler::SomeProcessor,
1923 &ArrayBuiltinsAssembler::NullPostLoopAction,
1924 Builtins::CallableFor(isolate(), Builtins::kArraySomeLoopContinuation),
1925 MissingPropertyMode::kSkip);
1928 TF_BUILTIN(TypedArrayPrototypeSome, ArrayBuiltinsAssembler) {
1929 TNode<IntPtrT> argc =
1930 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
1931 CodeStubArguments args(
this, argc);
1932 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1933 TNode<Object> receiver = args.GetReceiver();
1934 Node* callbackfn = args.GetOptionalArgumentValue(0);
1935 Node* this_arg = args.GetOptionalArgumentValue(1);
1937 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
1939 GenerateIteratingTypedArrayBuiltinBody(
1940 "%TypedArray%.prototype.some",
1941 &ArrayBuiltinsAssembler::SomeResultGenerator,
1942 &ArrayBuiltinsAssembler::SomeProcessor,
1943 &ArrayBuiltinsAssembler::NullPostLoopAction);
1946 TF_BUILTIN(ArrayEveryLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
1947 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1948 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1949 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1950 Node* this_arg = Parameter(Descriptor::kThisArg);
1951 Node* initial_k = Parameter(Descriptor::kInitialK);
1952 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1953 Node* result = Parameter(Descriptor::kResult);
1958 Label true_continue(
this), false_continue(
this);
1961 BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
1962 BIND(&true_continue);
1965 initial_k = NumberInc(initial_k);
1967 Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
1968 callbackfn, this_arg, TrueConstant(), receiver,
1969 initial_k, len, UndefinedConstant()));
1971 BIND(&false_continue);
1972 { Return(FalseConstant()); }
1975 TF_BUILTIN(ArrayEveryLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
1976 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1977 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1978 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1979 Node* this_arg = Parameter(Descriptor::kThisArg);
1980 Node* initial_k = Parameter(Descriptor::kInitialK);
1981 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1983 Return(CallBuiltin(Builtins::kArrayEveryLoopContinuation, context, receiver,
1984 callbackfn, this_arg, TrueConstant(), receiver, initial_k,
1985 len, UndefinedConstant()));
1988 TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinsAssembler) {
1989 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
1990 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
1991 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
1992 Node* this_arg = Parameter(Descriptor::kThisArg);
1993 Node* array = Parameter(Descriptor::kArray);
1994 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
1995 Node* initial_k = Parameter(Descriptor::kInitialK);
1996 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
1997 Node* to = Parameter(Descriptor::kTo);
1999 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
2000 this_arg, array,
object, initial_k,
2003 GenerateIteratingArrayBuiltinLoopContinuation(
2004 &ArrayBuiltinsAssembler::EveryProcessor,
2005 &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
2008 TF_BUILTIN(ArrayEvery, ArrayBuiltinsAssembler) {
2009 TNode<IntPtrT> argc =
2010 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2011 CodeStubArguments args(
this, argc);
2012 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2013 TNode<Object> receiver = args.GetReceiver();
2014 Node* callbackfn = args.GetOptionalArgumentValue(0);
2015 Node* this_arg = args.GetOptionalArgumentValue(1);
2017 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
2019 GenerateIteratingArrayBuiltinBody(
2020 "Array.prototype.every", &ArrayBuiltinsAssembler::EveryResultGenerator,
2021 &ArrayBuiltinsAssembler::EveryProcessor,
2022 &ArrayBuiltinsAssembler::NullPostLoopAction,
2023 Builtins::CallableFor(isolate(), Builtins::kArrayEveryLoopContinuation),
2024 MissingPropertyMode::kSkip);
2027 TF_BUILTIN(TypedArrayPrototypeEvery, ArrayBuiltinsAssembler) {
2028 TNode<IntPtrT> argc =
2029 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2030 CodeStubArguments args(
this, argc);
2031 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2032 TNode<Object> receiver = args.GetReceiver();
2033 Node* callbackfn = args.GetOptionalArgumentValue(0);
2034 Node* this_arg = args.GetOptionalArgumentValue(1);
2036 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
2038 GenerateIteratingTypedArrayBuiltinBody(
2039 "%TypedArray%.prototype.every",
2040 &ArrayBuiltinsAssembler::EveryResultGenerator,
2041 &ArrayBuiltinsAssembler::EveryProcessor,
2042 &ArrayBuiltinsAssembler::NullPostLoopAction);
2045 TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinsAssembler) {
2046 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2047 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2048 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2049 Node* this_arg = Parameter(Descriptor::kThisArg);
2050 Node* accumulator = Parameter(Descriptor::kAccumulator);
2051 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
2052 Node* initial_k = Parameter(Descriptor::kInitialK);
2053 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2054 Node* to = Parameter(Descriptor::kTo);
2056 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
2057 this_arg, accumulator,
object,
2058 initial_k, len, to);
2060 GenerateIteratingArrayBuiltinLoopContinuation(
2061 &ArrayBuiltinsAssembler::ReduceProcessor,
2062 &ArrayBuiltinsAssembler::ReducePostLoopAction,
2063 MissingPropertyMode::kSkip);
2066 TF_BUILTIN(ArrayReducePreLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
2067 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2068 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2069 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2070 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2075 Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
2076 callbackfn, UndefinedConstant(), TheHoleConstant(),
2077 receiver, SmiConstant(0), len, UndefinedConstant()));
2080 TF_BUILTIN(ArrayReduceLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
2081 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2082 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2083 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2084 Node* accumulator = Parameter(Descriptor::kAccumulator);
2085 Node* initial_k = Parameter(Descriptor::kInitialK);
2086 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2088 Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
2089 callbackfn, UndefinedConstant(), accumulator, receiver,
2090 initial_k, len, UndefinedConstant()));
2093 TF_BUILTIN(ArrayReduceLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
2094 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2095 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2096 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2097 Node* initial_k = Parameter(Descriptor::kInitialK);
2098 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2099 Node* result = Parameter(Descriptor::kResult);
2101 Return(CallBuiltin(Builtins::kArrayReduceLoopContinuation, context, receiver,
2102 callbackfn, UndefinedConstant(), result, receiver,
2103 initial_k, len, UndefinedConstant()));
2106 TF_BUILTIN(ArrayReduce, ArrayBuiltinsAssembler) {
2107 TNode<IntPtrT> argc =
2108 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2109 CodeStubArguments args(
this, argc);
2110 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2111 TNode<Object> receiver = args.GetReceiver();
2112 Node* callbackfn = args.GetOptionalArgumentValue(0);
2113 Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
2115 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
2118 GenerateIteratingArrayBuiltinBody(
2119 "Array.prototype.reduce", &ArrayBuiltinsAssembler::ReduceResultGenerator,
2120 &ArrayBuiltinsAssembler::ReduceProcessor,
2121 &ArrayBuiltinsAssembler::ReducePostLoopAction,
2122 Builtins::CallableFor(isolate(), Builtins::kArrayReduceLoopContinuation),
2123 MissingPropertyMode::kSkip);
2126 TF_BUILTIN(TypedArrayPrototypeReduce, ArrayBuiltinsAssembler) {
2127 TNode<IntPtrT> argc =
2128 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2129 CodeStubArguments args(
this, argc);
2130 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2131 TNode<Object> receiver = args.GetReceiver();
2132 Node* callbackfn = args.GetOptionalArgumentValue(0);
2133 Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
2135 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
2138 GenerateIteratingTypedArrayBuiltinBody(
2139 "%TypedArray%.prototype.reduce",
2140 &ArrayBuiltinsAssembler::ReduceResultGenerator,
2141 &ArrayBuiltinsAssembler::ReduceProcessor,
2142 &ArrayBuiltinsAssembler::ReducePostLoopAction);
2145 TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinsAssembler) {
2146 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2147 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2148 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2149 Node* this_arg = Parameter(Descriptor::kThisArg);
2150 Node* accumulator = Parameter(Descriptor::kAccumulator);
2151 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
2152 Node* initial_k = Parameter(Descriptor::kInitialK);
2153 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2154 Node* to = Parameter(Descriptor::kTo);
2156 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
2157 this_arg, accumulator,
object,
2158 initial_k, len, to);
2160 GenerateIteratingArrayBuiltinLoopContinuation(
2161 &ArrayBuiltinsAssembler::ReduceProcessor,
2162 &ArrayBuiltinsAssembler::ReducePostLoopAction, MissingPropertyMode::kSkip,
2163 ForEachDirection::kReverse);
2166 TF_BUILTIN(ArrayReduceRightPreLoopEagerDeoptContinuation,
2167 ArrayBuiltinsAssembler) {
2168 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2169 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2170 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2171 TNode<Smi> len = CAST(Parameter(Descriptor::kLength));
2176 Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
2177 receiver, callbackfn, UndefinedConstant(),
2178 TheHoleConstant(), receiver, SmiSub(len, SmiConstant(1)),
2179 len, UndefinedConstant()));
2182 TF_BUILTIN(ArrayReduceRightLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
2183 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2184 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2185 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2186 Node* accumulator = Parameter(Descriptor::kAccumulator);
2187 Node* initial_k = Parameter(Descriptor::kInitialK);
2188 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2190 Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
2191 receiver, callbackfn, UndefinedConstant(), accumulator,
2192 receiver, initial_k, len, UndefinedConstant()));
2195 TF_BUILTIN(ArrayReduceRightLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
2196 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2197 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2198 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2199 Node* initial_k = Parameter(Descriptor::kInitialK);
2200 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2201 Node* result = Parameter(Descriptor::kResult);
2203 Return(CallBuiltin(Builtins::kArrayReduceRightLoopContinuation, context,
2204 receiver, callbackfn, UndefinedConstant(), result,
2205 receiver, initial_k, len, UndefinedConstant()));
2208 TF_BUILTIN(ArrayReduceRight, ArrayBuiltinsAssembler) {
2209 TNode<IntPtrT> argc =
2210 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2211 CodeStubArguments args(
this, argc);
2212 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2213 TNode<Object> receiver = args.GetReceiver();
2214 Node* callbackfn = args.GetOptionalArgumentValue(0);
2215 Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
2217 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
2220 GenerateIteratingArrayBuiltinBody(
2221 "Array.prototype.reduceRight",
2222 &ArrayBuiltinsAssembler::ReduceResultGenerator,
2223 &ArrayBuiltinsAssembler::ReduceProcessor,
2224 &ArrayBuiltinsAssembler::ReducePostLoopAction,
2225 Builtins::CallableFor(isolate(),
2226 Builtins::kArrayReduceRightLoopContinuation),
2227 MissingPropertyMode::kSkip, ForEachDirection::kReverse);
2230 TF_BUILTIN(TypedArrayPrototypeReduceRight, ArrayBuiltinsAssembler) {
2231 TNode<IntPtrT> argc =
2232 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2233 CodeStubArguments args(
this, argc);
2234 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2235 TNode<Object> receiver = args.GetReceiver();
2236 Node* callbackfn = args.GetOptionalArgumentValue(0);
2237 Node* initial_value = args.GetOptionalArgumentValue(1, TheHoleConstant());
2239 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, initial_value,
2242 GenerateIteratingTypedArrayBuiltinBody(
2243 "%TypedArray%.prototype.reduceRight",
2244 &ArrayBuiltinsAssembler::ReduceResultGenerator,
2245 &ArrayBuiltinsAssembler::ReduceProcessor,
2246 &ArrayBuiltinsAssembler::ReducePostLoopAction,
2247 ForEachDirection::kReverse);
2250 TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinsAssembler) {
2251 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2252 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2253 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2254 Node* this_arg = Parameter(Descriptor::kThisArg);
2255 Node* array = Parameter(Descriptor::kArray);
2256 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
2257 Node* initial_k = Parameter(Descriptor::kInitialK);
2258 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2259 Node* to = Parameter(Descriptor::kTo);
2261 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
2262 this_arg, array,
object, initial_k,
2265 GenerateIteratingArrayBuiltinLoopContinuation(
2266 &ArrayBuiltinsAssembler::FilterProcessor,
2267 &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
2270 TF_BUILTIN(ArrayFilterLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
2271 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2272 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2273 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2274 Node* this_arg = Parameter(Descriptor::kThisArg);
2275 Node* array = Parameter(Descriptor::kArray);
2276 Node* initial_k = Parameter(Descriptor::kInitialK);
2277 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2278 Node* to = Parameter(Descriptor::kTo);
2280 Return(CallBuiltin(Builtins::kArrayFilterLoopContinuation, context, receiver,
2281 callbackfn, this_arg, array, receiver, initial_k, len,
2285 TF_BUILTIN(ArrayFilterLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
2286 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2287 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2288 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2289 Node* this_arg = Parameter(Descriptor::kThisArg);
2290 Node* array = Parameter(Descriptor::kArray);
2291 Node* initial_k = Parameter(Descriptor::kInitialK);
2292 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2293 Node* value_k = Parameter(Descriptor::kValueK);
2294 Node* result = Parameter(Descriptor::kResult);
2296 VARIABLE(to, MachineRepresentation::kTagged, Parameter(Descriptor::kTo));
2303 Label true_continue(
this, &to), false_continue(
this);
2306 BranchIfToBooleanIsTrue(result, &true_continue, &false_continue);
2307 BIND(&true_continue);
2310 CallRuntime(Runtime::kCreateDataProperty, context, array, to.value(),
2313 to.Bind(NumberInc(to.value()));
2314 Goto(&false_continue);
2316 BIND(&false_continue);
2319 initial_k = NumberInc(initial_k);
2321 Return(CallBuiltin(Builtins::kArrayFilterLoopContinuation, context, receiver,
2322 callbackfn, this_arg, array, receiver, initial_k, len,
2326 TF_BUILTIN(ArrayFilter, ArrayBuiltinsAssembler) {
2327 TNode<IntPtrT> argc =
2328 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2329 CodeStubArguments args(
this, argc);
2330 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2331 TNode<Object> receiver = args.GetReceiver();
2332 Node* callbackfn = args.GetOptionalArgumentValue(0);
2333 Node* this_arg = args.GetOptionalArgumentValue(1);
2335 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
2337 GenerateIteratingArrayBuiltinBody(
2338 "Array.prototype.filter", &ArrayBuiltinsAssembler::FilterResultGenerator,
2339 &ArrayBuiltinsAssembler::FilterProcessor,
2340 &ArrayBuiltinsAssembler::NullPostLoopAction,
2341 Builtins::CallableFor(isolate(), Builtins::kArrayFilterLoopContinuation),
2342 MissingPropertyMode::kSkip);
2345 TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinsAssembler) {
2346 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2347 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2348 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2349 Node* this_arg = Parameter(Descriptor::kThisArg);
2350 Node* array = Parameter(Descriptor::kArray);
2351 TNode<JSReceiver>
object = CAST(Parameter(Descriptor::kObject));
2352 Node* initial_k = Parameter(Descriptor::kInitialK);
2353 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2354 Node* to = Parameter(Descriptor::kTo);
2356 InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
2357 this_arg, array,
object, initial_k,
2360 GenerateIteratingArrayBuiltinLoopContinuation(
2361 &ArrayBuiltinsAssembler::SpecCompliantMapProcessor,
2362 &ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
2365 TF_BUILTIN(ArrayMapLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
2366 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2367 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2368 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2369 Node* this_arg = Parameter(Descriptor::kThisArg);
2370 Node* array = Parameter(Descriptor::kArray);
2371 Node* initial_k = Parameter(Descriptor::kInitialK);
2372 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2374 Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
2375 callbackfn, this_arg, array, receiver, initial_k, len,
2376 UndefinedConstant()));
2379 TF_BUILTIN(ArrayMapLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
2380 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2381 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
2382 Node* callbackfn = Parameter(Descriptor::kCallbackFn);
2383 Node* this_arg = Parameter(Descriptor::kThisArg);
2384 Node* array = Parameter(Descriptor::kArray);
2385 Node* initial_k = Parameter(Descriptor::kInitialK);
2386 TNode<Number> len = CAST(Parameter(Descriptor::kLength));
2387 Node* result = Parameter(Descriptor::kResult);
2395 CallRuntime(Runtime::kCreateDataProperty, context, array, initial_k, result);
2397 initial_k = NumberInc(initial_k);
2399 Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
2400 callbackfn, this_arg, array, receiver, initial_k, len,
2401 UndefinedConstant()));
2404 TF_BUILTIN(ArrayMap, ArrayBuiltinsAssembler) {
2405 TNode<IntPtrT> argc =
2406 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2407 CodeStubArguments args(
this, argc);
2408 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2409 TNode<Object> receiver = args.GetReceiver();
2410 Node* callbackfn = args.GetOptionalArgumentValue(0);
2411 Node* this_arg = args.GetOptionalArgumentValue(1);
2413 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
2415 GenerateIteratingArrayBuiltinBody(
2416 "Array.prototype.map", &ArrayBuiltinsAssembler::MapResultGenerator,
2417 &ArrayBuiltinsAssembler::FastMapProcessor,
2418 &ArrayBuiltinsAssembler::NullPostLoopAction,
2419 Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation),
2420 MissingPropertyMode::kSkip);
2423 TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) {
2424 TNode<IntPtrT> argc =
2425 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2426 CodeStubArguments args(
this, argc);
2427 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2428 TNode<Object> receiver = args.GetReceiver();
2429 Node* callbackfn = args.GetOptionalArgumentValue(0);
2430 Node* this_arg = args.GetOptionalArgumentValue(1);
2432 InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
2434 GenerateIteratingTypedArrayBuiltinBody(
2435 "%TypedArray%.prototype.map",
2436 &ArrayBuiltinsAssembler::TypedArrayMapResultGenerator,
2437 &ArrayBuiltinsAssembler::TypedArrayMapProcessor,
2438 &ArrayBuiltinsAssembler::NullPostLoopAction);
2441 TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
2442 TNode<Object>
object = CAST(Parameter(Descriptor::kArg));
2443 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2445 Label call_runtime(
this), return_true(
this), return_false(
this);
2447 GotoIf(TaggedIsSmi(
object), &return_false);
2448 TNode<Int32T> instance_type = LoadInstanceType(CAST(
object));
2450 GotoIf(InstanceTypeEqual(instance_type, JS_ARRAY_TYPE), &return_true);
2453 Branch(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), &call_runtime,
2457 Return(TrueConstant());
2459 BIND(&return_false);
2460 Return(FalseConstant());
2462 BIND(&call_runtime);
2463 Return(CallRuntime(Runtime::kArrayIsArray, context,
object));
2471 enum SearchVariant { kIncludes, kIndexOf };
2475 void GenerateSmiOrObject(SearchVariant variant,
Node* context,
Node* elements,
2476 Node* search_element,
Node* array_length,
2478 void GeneratePackedDoubles(SearchVariant variant,
Node* elements,
2479 Node* search_element,
Node* array_length,
2481 void GenerateHoleyDoubles(SearchVariant variant,
Node* elements,
2482 Node* search_element,
Node* array_length,
2486 void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant,
2489 const int kSearchElementArg = 0;
2490 const int kFromIndexArg = 1;
2496 args.GetOptionalArgumentValue(kSearchElementArg);
2498 Node* intptr_zero = IntPtrConstant(0);
2500 Label init_index(
this), return_not_found(
this), call_runtime(
this);
2504 BranchIfFastJSArray(receiver, context, &init_index, &call_runtime);
2507 VARIABLE(index_var, MachineType::PointerRepresentation(), intptr_zero);
2511 CSA_ASSERT(
this, TaggedIsPositiveSmi(LoadJSArrayLength(array)));
2512 Node* array_length = LoadFastJSArrayLength(array);
2513 Node* array_length_untagged = SmiUntag(array_length);
2517 Label is_smi(
this), is_nonsmi(
this), done(
this);
2520 GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done);
2522 Node* start_from = args.AtIndex(kFromIndexArg);
2527 Branch(TaggedIsSmi(start_from), &is_smi, &is_nonsmi);
2531 GotoIfNot(IsUndefined(start_from), &call_runtime);
2536 Node* intptr_start_from = SmiUntag(start_from);
2537 index_var.Bind(intptr_start_from);
2539 GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
2541 index_var.Bind(IntPtrAdd(array_length_untagged, index_var.value()));
2543 GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), intptr_zero), &done);
2544 index_var.Bind(intptr_zero);
2551 GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), array_length_untagged),
2554 Label if_smiorobjects(
this), if_packed_doubles(
this), if_holey_doubles(
this);
2556 TNode<Int32T> elements_kind = LoadElementsKind(array);
2557 Node* elements = LoadElements(array);
2558 STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
2559 STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
2560 STATIC_ASSERT(PACKED_ELEMENTS == 2);
2561 STATIC_ASSERT(HOLEY_ELEMENTS == 3);
2562 GotoIf(Uint32LessThanOrEqual(elements_kind, Int32Constant(HOLEY_ELEMENTS)),
2564 GotoIf(Word32Equal(elements_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
2565 &if_packed_doubles);
2566 GotoIf(Word32Equal(elements_kind, Int32Constant(HOLEY_DOUBLE_ELEMENTS)),
2568 Goto(&return_not_found);
2570 BIND(&if_smiorobjects);
2573 (variant == kIncludes)
2574 ? Builtins::CallableFor(isolate(),
2575 Builtins::kArrayIncludesSmiOrObject)
2576 : Builtins::CallableFor(isolate(),
2577 Builtins::kArrayIndexOfSmiOrObject);
2578 Node* result = CallStub(callable, context, elements, search_element,
2579 array_length, SmiTag(index_var.value()));
2580 args.PopAndReturn(result);
2583 BIND(&if_packed_doubles);
2586 (variant == kIncludes)
2587 ? Builtins::CallableFor(isolate(),
2588 Builtins::kArrayIncludesPackedDoubles)
2589 : Builtins::CallableFor(isolate(),
2590 Builtins::kArrayIndexOfPackedDoubles);
2591 Node* result = CallStub(callable, context, elements, search_element,
2592 array_length, SmiTag(index_var.value()));
2593 args.PopAndReturn(result);
2596 BIND(&if_holey_doubles);
2599 (variant == kIncludes)
2600 ? Builtins::CallableFor(isolate(),
2601 Builtins::kArrayIncludesHoleyDoubles)
2602 : Builtins::CallableFor(isolate(),
2603 Builtins::kArrayIndexOfHoleyDoubles);
2604 Node* result = CallStub(callable, context, elements, search_element,
2605 array_length, SmiTag(index_var.value()));
2606 args.PopAndReturn(result);
2609 BIND(&return_not_found);
2610 if (variant == kIncludes) {
2611 args.PopAndReturn(FalseConstant());
2613 args.PopAndReturn(NumberConstant(-1));
2616 BIND(&call_runtime);
2619 args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant());
2620 Runtime::FunctionId
function = variant == kIncludes
2621 ? Runtime::kArrayIncludes_Slow
2622 : Runtime::kArrayIndexOf;
2624 CallRuntime(
function, context, array, search_element, start_from));
2628 void ArrayIncludesIndexofAssembler::GenerateSmiOrObject(
2629 SearchVariant variant, Node* context, Node* elements, Node* search_element,
2630 Node* array_length, Node* from_index) {
2631 VARIABLE(index_var, MachineType::PointerRepresentation(),
2632 SmiUntag(from_index));
2633 VARIABLE(search_num, MachineRepresentation::kFloat64);
2634 Node* array_length_untagged = SmiUntag(array_length);
2636 Label ident_loop(
this, &index_var), heap_num_loop(
this, &search_num),
2637 string_loop(
this), bigint_loop(
this, &index_var),
2638 undef_loop(
this, &index_var), not_smi(
this), not_heap_num(
this),
2639 return_found(
this), return_not_found(
this);
2641 GotoIfNot(TaggedIsSmi(search_element), ¬_smi);
2642 search_num.Bind(SmiToFloat64(search_element));
2643 Goto(&heap_num_loop);
2646 if (variant == kIncludes) {
2647 GotoIf(IsUndefined(search_element), &undef_loop);
2649 Node* map = LoadMap(search_element);
2650 GotoIfNot(IsHeapNumberMap(map), ¬_heap_num);
2651 search_num.Bind(LoadHeapNumberValue(search_element));
2652 Goto(&heap_num_loop);
2654 BIND(¬_heap_num);
2655 Node* search_type = LoadMapInstanceType(map);
2656 GotoIf(IsStringInstanceType(search_type), &string_loop);
2657 GotoIf(IsBigIntInstanceType(search_type), &bigint_loop);
2662 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2664 Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
2665 GotoIf(WordEqual(element_k, search_element), &return_found);
2667 Increment(&index_var);
2671 if (variant == kIncludes) {
2674 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2676 Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
2677 GotoIf(IsUndefined(element_k), &return_found);
2678 GotoIf(IsTheHole(element_k), &return_found);
2680 Increment(&index_var);
2684 BIND(&heap_num_loop);
2686 Label nan_loop(
this, &index_var), not_nan_loop(
this, &index_var);
2687 Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
2688 BranchIfFloat64IsNaN(search_num.value(), nan_handling, ¬_nan_loop);
2690 BIND(¬_nan_loop);
2692 Label continue_loop(
this), not_smi(
this);
2693 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2696 LoadFixedArrayElement(CAST(elements), index_var.value());
2697 GotoIfNot(TaggedIsSmi(element_k), ¬_smi);
2698 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)),
2699 &return_found, &continue_loop);
2702 GotoIfNot(IsHeapNumber(element_k), &continue_loop);
2703 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)),
2704 &return_found, &continue_loop);
2706 BIND(&continue_loop);
2707 Increment(&index_var);
2708 Goto(¬_nan_loop);
2712 if (variant == kIncludes) {
2714 Label continue_loop(
this);
2715 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2718 LoadFixedArrayElement(CAST(elements), index_var.value());
2719 GotoIf(TaggedIsSmi(element_k), &continue_loop);
2720 GotoIfNot(IsHeapNumber(CAST(element_k)), &continue_loop);
2721 BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_found,
2724 BIND(&continue_loop);
2725 Increment(&index_var);
2732 TNode<String> search_element_string = CAST(search_element);
2733 Label continue_loop(
this), next_iteration(
this, &index_var),
2734 slow_compare(
this), runtime(
this, Label::kDeferred);
2735 TNode<IntPtrT> search_length =
2736 LoadStringLengthAsWord(search_element_string);
2737 Goto(&next_iteration);
2738 BIND(&next_iteration);
2739 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2741 Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
2742 GotoIf(TaggedIsSmi(element_k), &continue_loop);
2743 GotoIf(WordEqual(search_element_string, element_k), &return_found);
2744 Node* element_k_type = LoadInstanceType(element_k);
2745 GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop);
2746 Branch(WordEqual(search_length, LoadStringLengthAsWord(element_k)),
2747 &slow_compare, &continue_loop);
2749 BIND(&slow_compare);
2750 StringBuiltinsAssembler string_asm(state());
2751 string_asm.StringEqual_Core(context, search_element_string, search_type,
2752 element_k, element_k_type, search_length,
2753 &return_found, &continue_loop, &runtime);
2755 TNode<Object> result = CallRuntime(Runtime::kStringEqual, context,
2756 search_element_string, element_k);
2757 Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
2759 BIND(&continue_loop);
2760 Increment(&index_var);
2761 Goto(&next_iteration);
2766 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2769 Node* element_k = LoadFixedArrayElement(CAST(elements), index_var.value());
2770 Label continue_loop(
this);
2771 GotoIf(TaggedIsSmi(element_k), &continue_loop);
2772 GotoIfNot(IsBigInt(CAST(element_k)), &continue_loop);
2773 TNode<Object> result = CallRuntime(Runtime::kBigIntEqualToBigInt, context,
2774 search_element, element_k);
2775 Branch(WordEqual(result, TrueConstant()), &return_found, &continue_loop);
2777 BIND(&continue_loop);
2778 Increment(&index_var);
2781 BIND(&return_found);
2782 if (variant == kIncludes) {
2783 Return(TrueConstant());
2785 Return(SmiTag(index_var.value()));
2788 BIND(&return_not_found);
2789 if (variant == kIncludes) {
2790 Return(FalseConstant());
2792 Return(NumberConstant(-1));
2796 void ArrayIncludesIndexofAssembler::GeneratePackedDoubles(SearchVariant variant,
2798 Node* search_element,
2801 VARIABLE(index_var, MachineType::PointerRepresentation(),
2802 SmiUntag(from_index));
2803 Node* array_length_untagged = SmiUntag(array_length);
2805 Label nan_loop(
this, &index_var), not_nan_loop(
this, &index_var),
2806 hole_loop(
this, &index_var), search_notnan(
this), return_found(
this),
2807 return_not_found(
this);
2808 VARIABLE(search_num, MachineRepresentation::kFloat64);
2809 search_num.Bind(Float64Constant(0));
2811 GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
2812 search_num.Bind(SmiToFloat64(search_element));
2813 Goto(¬_nan_loop);
2815 BIND(&search_notnan);
2816 GotoIfNot(IsHeapNumber(search_element), &return_not_found);
2818 search_num.Bind(LoadHeapNumberValue(search_element));
2820 Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
2821 BranchIfFloat64IsNaN(search_num.value(), nan_handling, ¬_nan_loop);
2823 BIND(¬_nan_loop);
2825 Label continue_loop(
this);
2826 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2828 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
2829 MachineType::Float64());
2830 Branch(Float64Equal(element_k, search_num.value()), &return_found,
2832 BIND(&continue_loop);
2833 Increment(&index_var);
2834 Goto(¬_nan_loop);
2838 if (variant == kIncludes) {
2840 Label continue_loop(
this);
2841 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2843 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
2844 MachineType::Float64());
2845 BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
2846 BIND(&continue_loop);
2847 Increment(&index_var);
2851 BIND(&return_found);
2852 if (variant == kIncludes) {
2853 Return(TrueConstant());
2855 Return(SmiTag(index_var.value()));
2858 BIND(&return_not_found);
2859 if (variant == kIncludes) {
2860 Return(FalseConstant());
2862 Return(NumberConstant(-1));
2866 void ArrayIncludesIndexofAssembler::GenerateHoleyDoubles(SearchVariant variant,
2868 Node* search_element,
2871 VARIABLE(index_var, MachineType::PointerRepresentation(),
2872 SmiUntag(from_index));
2873 Node* array_length_untagged = SmiUntag(array_length);
2875 Label nan_loop(
this, &index_var), not_nan_loop(
this, &index_var),
2876 hole_loop(
this, &index_var), search_notnan(
this), return_found(
this),
2877 return_not_found(
this);
2878 VARIABLE(search_num, MachineRepresentation::kFloat64);
2879 search_num.Bind(Float64Constant(0));
2881 GotoIfNot(TaggedIsSmi(search_element), &search_notnan);
2882 search_num.Bind(SmiToFloat64(search_element));
2883 Goto(¬_nan_loop);
2885 BIND(&search_notnan);
2886 if (variant == kIncludes) {
2887 GotoIf(IsUndefined(search_element), &hole_loop);
2889 GotoIfNot(IsHeapNumber(search_element), &return_not_found);
2891 search_num.Bind(LoadHeapNumberValue(search_element));
2893 Label* nan_handling = variant == kIncludes ? &nan_loop : &return_not_found;
2894 BranchIfFloat64IsNaN(search_num.value(), nan_handling, ¬_nan_loop);
2896 BIND(¬_nan_loop);
2898 Label continue_loop(
this);
2899 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2904 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(),
2905 MachineType::Float64());
2907 Branch(Float64Equal(element_k, search_num.value()), &return_found,
2909 BIND(&continue_loop);
2910 Increment(&index_var);
2911 Goto(¬_nan_loop);
2915 if (variant == kIncludes) {
2917 Label continue_loop(
this);
2918 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2922 Node* element_k = LoadFixedDoubleArrayElement(
2923 elements, index_var.value(), MachineType::Float64(), 0,
2924 INTPTR_PARAMETERS, &continue_loop);
2926 BranchIfFloat64IsNaN(element_k, &return_found, &continue_loop);
2927 BIND(&continue_loop);
2928 Increment(&index_var);
2933 if (variant == kIncludes) {
2935 GotoIfNot(UintPtrLessThan(index_var.value(), array_length_untagged),
2939 LoadFixedDoubleArrayElement(elements, index_var.value(),
2940 MachineType::None(), 0, INTPTR_PARAMETERS,
2943 Increment(&index_var);
2947 BIND(&return_found);
2948 if (variant == kIncludes) {
2949 Return(TrueConstant());
2951 Return(SmiTag(index_var.value()));
2954 BIND(&return_not_found);
2955 if (variant == kIncludes) {
2956 Return(FalseConstant());
2958 Return(NumberConstant(-1));
2962 TF_BUILTIN(ArrayIncludes, ArrayIncludesIndexofAssembler) {
2963 TNode<IntPtrT> argc =
2964 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
2965 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
2967 Generate(kIncludes, argc, context);
2970 TF_BUILTIN(ArrayIncludesSmiOrObject, ArrayIncludesIndexofAssembler) {
2971 Node* context = Parameter(Descriptor::kContext);
2972 Node* elements = Parameter(Descriptor::kElements);
2973 Node* search_element = Parameter(Descriptor::kSearchElement);
2974 Node* array_length = Parameter(Descriptor::kLength);
2975 Node* from_index = Parameter(Descriptor::kFromIndex);
2977 GenerateSmiOrObject(kIncludes, context, elements, search_element,
2978 array_length, from_index);
2981 TF_BUILTIN(ArrayIncludesPackedDoubles, ArrayIncludesIndexofAssembler) {
2982 Node* elements = Parameter(Descriptor::kElements);
2983 Node* search_element = Parameter(Descriptor::kSearchElement);
2984 Node* array_length = Parameter(Descriptor::kLength);
2985 Node* from_index = Parameter(Descriptor::kFromIndex);
2987 GeneratePackedDoubles(kIncludes, elements, search_element, array_length,
2991 TF_BUILTIN(ArrayIncludesHoleyDoubles, ArrayIncludesIndexofAssembler) {
2992 Node* elements = Parameter(Descriptor::kElements);
2993 Node* search_element = Parameter(Descriptor::kSearchElement);
2994 Node* array_length = Parameter(Descriptor::kLength);
2995 Node* from_index = Parameter(Descriptor::kFromIndex);
2997 GenerateHoleyDoubles(kIncludes, elements, search_element, array_length,
3001 TF_BUILTIN(ArrayIndexOf, ArrayIncludesIndexofAssembler) {
3002 TNode<IntPtrT> argc =
3003 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
3004 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3006 Generate(kIndexOf, argc, context);
3009 TF_BUILTIN(ArrayIndexOfSmiOrObject, ArrayIncludesIndexofAssembler) {
3010 Node* context = Parameter(Descriptor::kContext);
3011 Node* elements = Parameter(Descriptor::kElements);
3012 Node* search_element = Parameter(Descriptor::kSearchElement);
3013 Node* array_length = Parameter(Descriptor::kLength);
3014 Node* from_index = Parameter(Descriptor::kFromIndex);
3016 GenerateSmiOrObject(kIndexOf, context, elements, search_element, array_length,
3020 TF_BUILTIN(ArrayIndexOfPackedDoubles, ArrayIncludesIndexofAssembler) {
3021 Node* elements = Parameter(Descriptor::kElements);
3022 Node* search_element = Parameter(Descriptor::kSearchElement);
3023 Node* array_length = Parameter(Descriptor::kLength);
3024 Node* from_index = Parameter(Descriptor::kFromIndex);
3026 GeneratePackedDoubles(kIndexOf, elements, search_element, array_length,
3030 TF_BUILTIN(ArrayIndexOfHoleyDoubles, ArrayIncludesIndexofAssembler) {
3031 Node* elements = Parameter(Descriptor::kElements);
3032 Node* search_element = Parameter(Descriptor::kSearchElement);
3033 Node* array_length = Parameter(Descriptor::kLength);
3034 Node* from_index = Parameter(Descriptor::kFromIndex);
3036 GenerateHoleyDoubles(kIndexOf, elements, search_element, array_length,
3041 TF_BUILTIN(ArrayPrototypeValues, CodeStubAssembler) {
3042 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3043 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
3044 Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
3045 IterationKind::kValues));
3049 TF_BUILTIN(ArrayPrototypeEntries, CodeStubAssembler) {
3050 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3051 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
3052 Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
3053 IterationKind::kEntries));
3057 TF_BUILTIN(ArrayPrototypeKeys, CodeStubAssembler) {
3058 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3059 TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
3060 Return(CreateArrayIterator(context, ToObject_Inline(context, receiver),
3061 IterationKind::kKeys));
3065 TF_BUILTIN(ArrayIteratorPrototypeNext, CodeStubAssembler) {
3066 const char* method_name =
"Array Iterator.prototype.next";
3068 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3069 Node* iterator = Parameter(Descriptor::kReceiver);
3071 VARIABLE(var_done, MachineRepresentation::kTagged, TrueConstant());
3072 VARIABLE(var_value, MachineRepresentation::kTagged, UndefinedConstant());
3074 Label allocate_entry_if_needed(
this);
3075 Label allocate_iterator_result(
this);
3076 Label if_typedarray(
this), if_other(
this, Label::kDeferred), if_array(
this),
3077 if_generic(
this, Label::kDeferred);
3078 Label set_done(
this, Label::kDeferred);
3082 ThrowIfNotInstanceType(context, iterator, JS_ARRAY_ITERATOR_TYPE,
3086 TNode<JSReceiver> array =
3087 CAST(LoadObjectField(iterator, JSArrayIterator::kIteratedObjectOffset));
3090 TNode<Number> index =
3091 CAST(LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset));
3092 CSA_ASSERT(
this, IsNumberNonNegativeSafeInteger(index));
3095 TNode<Map> array_map = LoadMap(array);
3096 TNode<Int32T> array_type = LoadMapInstanceType(array_map);
3097 GotoIf(InstanceTypeEqual(array_type, JS_ARRAY_TYPE), &if_array);
3098 Branch(InstanceTypeEqual(array_type, JS_TYPED_ARRAY_TYPE), &if_typedarray,
3104 CSA_ASSERT(
this, IsNumberArrayIndex(index));
3108 TNode<Uint32T> index32 = ChangeNumberToUint32(index);
3109 TNode<Uint32T> length32 =
3110 ChangeNumberToUint32(LoadJSArrayLength(CAST(array)));
3111 GotoIfNot(Uint32LessThan(index32, length32), &set_done);
3113 iterator, JSArrayIterator::kNextIndexOffset,
3114 ChangeUint32ToTagged(Unsigned(Int32Add(index32, Int32Constant(1)))));
3116 var_done.Bind(FalseConstant());
3117 var_value.Bind(index);
3119 GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
3120 iterator, JSArrayIterator::kKindOffset),
3121 Int32Constant(static_cast<int>(IterationKind::kKeys))),
3122 &allocate_iterator_result);
3124 Label if_hole(
this, Label::kDeferred);
3125 TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
3126 TNode<FixedArrayBase> elements = LoadElements(CAST(array));
3127 GotoIfForceSlowPath(&if_generic);
3128 var_value.Bind(LoadFixedArrayBaseElementAsTagged(
3129 elements, Signed(ChangeUint32ToWord(index32)), elements_kind,
3130 &if_generic, &if_hole));
3131 Goto(&allocate_entry_if_needed);
3135 GotoIf(IsNoElementsProtectorCellInvalid(), &if_generic);
3136 GotoIfNot(IsPrototypeInitialArrayPrototype(context, array_map),
3138 var_value.Bind(UndefinedConstant());
3139 Goto(&allocate_entry_if_needed);
3146 CSA_ASSERT(
this, Word32BinaryNot(IsJSArray(array)));
3147 CSA_ASSERT(
this, Word32BinaryNot(IsJSTypedArray(array)));
3150 TNode<Number> length = CAST(
3151 CallBuiltin(Builtins::kToLength, context,
3152 GetProperty(context, array, factory()->length_string())));
3153 GotoIfNumberGreaterThanOrEqual(index, length, &set_done);
3154 StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
3157 var_done.Bind(FalseConstant());
3158 var_value.Bind(index);
3160 Branch(Word32Equal(LoadAndUntagToWord32ObjectField(
3161 iterator, JSArrayIterator::kKindOffset),
3162 Int32Constant(static_cast<int>(IterationKind::kKeys))),
3163 &allocate_iterator_result, &if_generic);
3184 CSA_ASSERT(
this, Word32BinaryNot(IsJSTypedArray(array)));
3185 TNode<Number> max_length =
3186 SelectConstant(IsJSArray(array), NumberConstant(kMaxUInt32),
3187 NumberConstant(kMaxSafeInteger));
3188 StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset, max_length);
3189 Goto(&allocate_iterator_result);
3194 var_value.Bind(GetProperty(context, array, index));
3195 Goto(&allocate_entry_if_needed);
3198 BIND(&if_typedarray);
3201 CSA_ASSERT(
this, TaggedIsSmi(index));
3204 ThrowIfArrayBufferViewBufferIsDetached(context, CAST(array), method_name);
3210 TNode<Smi> length = LoadJSTypedArrayLength(CAST(array));
3211 GotoIfNot(SmiBelow(CAST(index), length), &allocate_iterator_result);
3212 StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
3213 SmiInc(CAST(index)));
3215 var_done.Bind(FalseConstant());
3216 var_value.Bind(index);
3218 GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
3219 iterator, JSArrayIterator::kKindOffset),
3220 Int32Constant(static_cast<int>(IterationKind::kKeys))),
3221 &allocate_iterator_result);
3223 TNode<Int32T> elements_kind = LoadMapElementsKind(array_map);
3224 Node* elements = LoadElements(CAST(array));
3226 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
3227 Node* external_ptr =
3228 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
3229 MachineType::Pointer());
3230 TNode<WordT> data_ptr =
3231 IntPtrAdd(BitcastTaggedToWord(base_ptr), external_ptr);
3232 var_value.Bind(LoadFixedTypedArrayElementAsTagged(data_ptr, CAST(index),
3234 Goto(&allocate_entry_if_needed);
3237 BIND(&allocate_entry_if_needed);
3239 GotoIf(Word32Equal(LoadAndUntagToWord32ObjectField(
3240 iterator, JSArrayIterator::kKindOffset),
3241 Int32Constant(static_cast<int>(IterationKind::kValues))),
3242 &allocate_iterator_result);
3245 AllocateJSIteratorResultForEntry(context, index, var_value.value());
3249 BIND(&allocate_iterator_result);
3252 AllocateJSIteratorResult(context, var_value.value(), var_done.value());
3265 Node* mapper_function =
nullptr,
3266 Node* this_arg =
nullptr) {
3267 CSA_ASSERT(
this, IsJSReceiver(target));
3268 CSA_ASSERT(
this, IsJSReceiver(source));
3269 CSA_ASSERT(
this, IsNumberPositive(source_length));
3270 CSA_ASSERT(
this, IsNumberPositive(start));
3271 CSA_ASSERT(
this, IsNumber(depth));
3274 VARIABLE(var_target_index, MachineRepresentation::kTagged, start);
3277 VARIABLE(var_source_index, MachineRepresentation::kTagged, SmiConstant(0));
3280 Label loop(
this, {&var_target_index, &var_source_index}), done_loop(
this);
3284 Node*
const source_index = var_source_index.value();
3285 Node*
const target_index = var_target_index.value();
3288 GotoIfNumberGreaterThanOrEqual(source_index, source_length, &done_loop);
3293 SmiGreaterThanOrEqual(CAST(source_index), SmiConstant(0)));
3294 Node*
const exists =
3295 HasProperty(context, source, source_index, kHasProperty);
3299 GotoIfNot(IsTrue(exists), &next);
3302 Node* element = GetProperty(context, source, source_index);
3305 if (mapper_function !=
nullptr) {
3306 CSA_ASSERT(
this, Word32Or(IsUndefined(mapper_function),
3307 IsCallable(mapper_function)));
3308 DCHECK_NOT_NULL(this_arg);
3313 CallJS(CodeFactory::Call(isolate()), context, mapper_function,
3314 this_arg, element, source_index, source);
3318 Label if_flatten_array(
this), if_flatten_proxy(
this, Label::kDeferred),
3321 GotoIfNumberGreaterThanOrEqual(SmiConstant(0), depth, &if_noflatten);
3323 GotoIf(TaggedIsSmi(element), &if_noflatten);
3324 GotoIf(IsJSArray(element), &if_flatten_array);
3325 GotoIfNot(IsJSProxy(element), &if_noflatten);
3326 Branch(IsTrue(
CallRuntime(Runtime::kArrayIsArray, context, element)),
3327 &if_flatten_proxy, &if_noflatten);
3329 BIND(&if_flatten_array);
3331 CSA_ASSERT(
this, IsJSArray(element));
3334 Node*
const element_length =
3335 LoadObjectField(element, JSArray::kLengthOffset);
3340 var_target_index.Bind(
3341 CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
3342 element_length, target_index, NumberDec(depth)));
3346 BIND(&if_flatten_proxy);
3348 CSA_ASSERT(
this, IsJSProxy(element));
3351 Node*
const element_length = ToLength_Inline(
3352 context, GetProperty(context, element, LengthStringConstant()));
3357 var_target_index.Bind(
3358 CallBuiltin(Builtins::kFlattenIntoArray, context, target, element,
3359 element_length, target_index, NumberDec(depth)));
3363 BIND(&if_noflatten);
3366 Label throw_error(
this, Label::kDeferred);
3367 GotoIfNumberGreaterThanOrEqual(
3368 target_index, NumberConstant(kMaxSafeInteger), &throw_error);
3373 CallRuntime(Runtime::kCreateDataProperty, context, target,
3374 target_index, element);
3377 var_target_index.Bind(NumberInc(target_index));
3381 ThrowTypeError(context, MessageTemplate::kFlattenPastSafeLength,
3382 source_length, target_index);
3388 var_source_index.Bind(NumberInc(source_index));
3393 return var_target_index.value();
3399 Node*
const context = Parameter(Descriptor::kContext);
3400 Node*
const target = Parameter(Descriptor::kTarget);
3401 Node*
const source = Parameter(Descriptor::kSource);
3402 Node*
const source_length = Parameter(Descriptor::kSourceLength);
3403 Node*
const start = Parameter(Descriptor::kStart);
3404 Node*
const depth = Parameter(Descriptor::kDepth);
3407 FlattenIntoArray(context, target, source, source_length, start, depth));
3411 TF_BUILTIN(FlatMapIntoArray, ArrayFlattenAssembler) {
3412 Node*
const context = Parameter(Descriptor::kContext);
3413 Node*
const target = Parameter(Descriptor::kTarget);
3414 Node*
const source = Parameter(Descriptor::kSource);
3415 Node*
const source_length = Parameter(Descriptor::kSourceLength);
3416 Node*
const start = Parameter(Descriptor::kStart);
3417 Node*
const depth = Parameter(Descriptor::kDepth);
3418 Node*
const mapper_function = Parameter(Descriptor::kMapperFunction);
3419 Node*
const this_arg = Parameter(Descriptor::kThisArg);
3421 Return(FlattenIntoArray(context, target, source, source_length, start, depth,
3422 mapper_function, this_arg));
3426 TF_BUILTIN(ArrayPrototypeFlat, CodeStubAssembler) {
3427 TNode<IntPtrT>
const argc =
3428 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
3429 CodeStubArguments args(
this, argc);
3430 TNode<Context>
const context = CAST(Parameter(Descriptor::kContext));
3431 TNode<Object>
const receiver = args.GetReceiver();
3432 TNode<Object>
const depth = args.GetOptionalArgumentValue(0);
3435 TNode<JSReceiver>
const o = ToObject_Inline(context, receiver);
3438 TNode<Number>
const source_length =
3439 ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
3442 TVARIABLE(Number, var_depth_num, SmiConstant(1));
3446 GotoIf(IsUndefined(depth), &done);
3449 var_depth_num = ToInteger_Inline(context, depth);
3455 TNode<JSReceiver>
const constructor =
3456 CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
3457 Node*
const a = Construct(context, constructor, SmiConstant(0));
3460 CallBuiltin(Builtins::kFlattenIntoArray, context, a, o, source_length,
3461 SmiConstant(0), var_depth_num.value());
3464 args.PopAndReturn(a);
3468 TF_BUILTIN(ArrayPrototypeFlatMap, CodeStubAssembler) {
3469 TNode<IntPtrT>
const argc =
3470 ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
3471 CodeStubArguments args(
this, argc);
3472 TNode<Context>
const context = CAST(Parameter(Descriptor::kContext));
3473 TNode<Object>
const receiver = args.GetReceiver();
3474 TNode<Object>
const mapper_function = args.GetOptionalArgumentValue(0);
3477 TNode<JSReceiver>
const o = ToObject_Inline(context, receiver);
3480 TNode<Number>
const source_length =
3481 ToLength_Inline(context, GetProperty(context, o, LengthStringConstant()));
3484 Label if_not_callable(
this, Label::kDeferred);
3485 GotoIf(TaggedIsSmi(mapper_function), &if_not_callable);
3486 GotoIfNot(IsCallable(CAST(mapper_function)), &if_not_callable);
3489 TNode<Object>
const t = args.GetOptionalArgumentValue(1);
3492 TNode<JSReceiver>
const constructor =
3493 CAST(CallRuntime(Runtime::kArraySpeciesConstructor, context, o));
3494 TNode<JSReceiver>
const a = Construct(context, constructor, SmiConstant(0));
3497 CallBuiltin(Builtins::kFlatMapIntoArray, context, a, o, source_length,
3498 SmiConstant(0), SmiConstant(1), mapper_function, t);
3501 args.PopAndReturn(a);
3503 BIND(&if_not_callable);
3504 { ThrowTypeError(context, MessageTemplate::kMapperFunctionNonCallable); }
3507 TF_BUILTIN(ArrayConstructor, ArrayBuiltinsAssembler) {
3510 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3511 TNode<JSFunction>
function = CAST(Parameter(Descriptor::kTarget));
3512 TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
3513 TNode<Int32T> argc =
3514 UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
3519 SelectConstant<Object>(IsUndefined(new_target),
function, new_target);
3522 TNode<Object> no_allocation_site = UndefinedConstant();
3523 TailCallBuiltin(Builtins::kArrayConstructorImpl, context,
function,
3524 new_target, argc, no_allocation_site);
3527 void ArrayBuiltinsAssembler::TailCallArrayConstructorStub(
3528 const Callable& callable, TNode<Context> context, TNode<JSFunction> target,
3529 TNode<HeapObject> allocation_site_or_undefined, TNode<Int32T> argc) {
3530 TNode<Code> code = HeapConstant(callable.code());
3546 TailCallStub(ArrayNArgumentsConstructorDescriptor{}, code, context, target,
3547 allocation_site_or_undefined, argc);
3550 void ArrayBuiltinsAssembler::CreateArrayDispatchNoArgument(
3551 TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
3552 AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
3553 if (mode == DISABLE_ALLOCATION_SITES) {
3554 Callable callable = CodeFactory::ArrayNoArgumentConstructor(
3555 isolate(), GetInitialFastElementsKind(), mode);
3557 TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
3560 DCHECK_EQ(mode, DONT_OVERRIDE);
3561 TNode<Int32T> elements_kind = LoadElementsKind(allocation_site);
3566 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
3567 for (
int i = 0;
i <= last_index; ++
i) {
3569 ElementsKind kind = GetFastElementsKindFromSequenceIndex(
i);
3570 GotoIfNot(Word32Equal(elements_kind, Int32Constant(kind)), &next);
3573 CodeFactory::ArrayNoArgumentConstructor(isolate(), kind, mode);
3575 TailCallArrayConstructorStub(callable, context, target, allocation_site,
3582 Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
3586 void ArrayBuiltinsAssembler::CreateArrayDispatchSingleArgument(
3587 TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
3588 AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
3589 if (mode == DISABLE_ALLOCATION_SITES) {
3590 ElementsKind initial = GetInitialFastElementsKind();
3591 ElementsKind holey_initial = GetHoleyElementsKind(initial);
3592 Callable callable = CodeFactory::ArraySingleArgumentConstructor(
3593 isolate(), holey_initial, mode);
3595 TailCallArrayConstructorStub(callable, context, target, UndefinedConstant(),
3598 DCHECK_EQ(mode, DONT_OVERRIDE);
3599 TNode<Smi> transition_info = LoadTransitionInfo(allocation_site);
3602 STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
3603 STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
3604 STATIC_ASSERT(PACKED_ELEMENTS == 2);
3605 STATIC_ASSERT(HOLEY_ELEMENTS == 3);
3606 STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
3607 STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
3609 Label normal_sequence(
this);
3610 TVARIABLE(Int32T, var_elements_kind,
3611 Signed(DecodeWord32<AllocationSite::ElementsKindBits>(
3612 SmiToInt32(transition_info))));
3614 int fast_elements_kind_holey_mask =
3615 AllocationSite::ElementsKindBits::encode(static_cast<ElementsKind>(1));
3616 GotoIf(IsSetSmi(transition_info, fast_elements_kind_holey_mask),
3621 Signed(Word32Or(var_elements_kind.value(), Int32Constant(1)));
3622 StoreObjectFieldNoWriteBarrier(
3623 allocation_site, AllocationSite::kTransitionInfoOrBoilerplateOffset,
3624 SmiOr(transition_info, SmiConstant(fast_elements_kind_holey_mask)));
3625 Goto(&normal_sequence);
3627 BIND(&normal_sequence);
3634 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
3635 for (
int i = 0;
i <= last_index; ++
i) {
3637 ElementsKind kind = GetFastElementsKindFromSequenceIndex(
i);
3638 GotoIfNot(Word32Equal(var_elements_kind.value(), Int32Constant(kind)),
3642 CodeFactory::ArraySingleArgumentConstructor(isolate(), kind, mode);
3644 TailCallArrayConstructorStub(callable, context, target, allocation_site,
3651 Abort(AbortReason::kUnexpectedElementsKindInArrayConstructor);
3655 void ArrayBuiltinsAssembler::GenerateDispatchToArrayStub(
3656 TNode<Context> context, TNode<JSFunction> target, TNode<Int32T> argc,
3657 AllocationSiteOverrideMode mode, TNode<AllocationSite> allocation_site) {
3658 Label check_one_case(
this), fallthrough(
this);
3659 GotoIfNot(Word32Equal(argc, Int32Constant(0)), &check_one_case);
3660 CreateArrayDispatchNoArgument(context, target, argc, mode, allocation_site);
3662 BIND(&check_one_case);
3663 GotoIfNot(Word32Equal(argc, Int32Constant(1)), &fallthrough);
3664 CreateArrayDispatchSingleArgument(context, target, argc, mode,
3670 TF_BUILTIN(ArrayConstructorImpl, ArrayBuiltinsAssembler) {
3671 TNode<JSFunction> target = CAST(Parameter(Descriptor::kTarget));
3672 TNode<Object> new_target = CAST(Parameter(Descriptor::kNewTarget));
3673 TNode<Int32T> argc =
3674 UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
3675 TNode<HeapObject> maybe_allocation_site =
3676 CAST(Parameter(Descriptor::kAllocationSite));
3679 CSA_ASSERT(
this, IsMap(CAST(LoadObjectField(
3680 target, JSFunction::kPrototypeOrInitialMapOffset))));
3683 CSA_ASSERT(
this, Word32Or(IsUndefined(maybe_allocation_site),
3684 IsAllocationSite(maybe_allocation_site)));
3687 TNode<Context> context =
3688 CAST(LoadObjectField(target, JSFunction::kContextOffset));
3690 Label runtime(
this, Label::kDeferred);
3691 GotoIf(WordNotEqual(target, new_target), &runtime);
3693 Label no_info(
this);
3696 GotoIf(IsUndefined(maybe_allocation_site), &no_info);
3698 GenerateDispatchToArrayStub(context, target, argc, DONT_OVERRIDE,
3699 CAST(maybe_allocation_site));
3703 GenerateDispatchToArrayStub(context, target, argc, DISABLE_ALLOCATION_SITES);
3707 GenerateArrayNArgumentsConstructor(context, target, new_target, argc,
3708 maybe_allocation_site);
3711 void ArrayBuiltinsAssembler::GenerateConstructor(
3712 Node* context, Node* array_function, Node* array_map, Node* array_size,
3713 Node* allocation_site, ElementsKind elements_kind,
3714 AllocationSiteMode mode) {
3716 Label smi_size(
this);
3717 Label small_smi_size(
this);
3718 Label call_runtime(
this, Label::kDeferred);
3720 Branch(TaggedIsSmi(array_size), &smi_size, &call_runtime);
3724 if (IsFastPackedElementsKind(elements_kind)) {
3725 Label abort(
this, Label::kDeferred);
3726 Branch(SmiEqual(CAST(array_size), SmiConstant(0)), &small_smi_size, &abort);
3729 Node* reason = SmiConstant(AbortReason::kAllocatingNonEmptyPackedArray);
3730 TailCallRuntime(Runtime::kAbort, context, reason);
3733 IsDoubleElementsKind(elements_kind) ? kDoubleSize : kPointerSize;
3734 int max_fast_elements =
3735 (kMaxRegularHeapObjectSize - FixedArray::kHeaderSize - JSArray::kSize -
3736 AllocationMemento::kSize) /
3738 Branch(SmiAboveOrEqual(CAST(array_size), SmiConstant(max_fast_elements)),
3739 &call_runtime, &small_smi_size);
3742 BIND(&small_smi_size);
3744 TNode<JSArray> array = AllocateJSArray(
3745 elements_kind, CAST(array_map), array_size, CAST(array_size),
3746 mode == DONT_TRACK_ALLOCATION_SITE ?
nullptr : allocation_site,
3747 CodeStubAssembler::SMI_PARAMETERS);
3751 BIND(&call_runtime);
3753 TailCallRuntime(Runtime::kNewArray, context, array_function, array_size,
3754 array_function, allocation_site);
3758 void ArrayBuiltinsAssembler::GenerateArrayNoArgumentConstructor(
3759 ElementsKind kind, AllocationSiteOverrideMode mode) {
3760 typedef ArrayNoArgumentConstructorDescriptor Descriptor;
3761 Node* native_context = LoadObjectField(Parameter(Descriptor::kFunction),
3762 JSFunction::kContextOffset);
3763 bool track_allocation_site =
3764 AllocationSite::ShouldTrack(kind) && mode != DISABLE_ALLOCATION_SITES;
3765 Node* allocation_site =
3766 track_allocation_site ? Parameter(Descriptor::kAllocationSite) : nullptr;
3767 TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context);
3768 TNode<JSArray> array = AllocateJSArray(
3769 kind, array_map, IntPtrConstant(JSArray::kPreallocatedArrayElements),
3770 SmiConstant(0), allocation_site);
3774 void ArrayBuiltinsAssembler::GenerateArraySingleArgumentConstructor(
3775 ElementsKind kind, AllocationSiteOverrideMode mode) {
3776 typedef ArraySingleArgumentConstructorDescriptor Descriptor;
3777 Node* context = Parameter(Descriptor::kContext);
3778 Node*
function = Parameter(Descriptor::kFunction);
3779 Node* native_context = LoadObjectField(
function, JSFunction::kContextOffset);
3780 Node* array_map = LoadJSArrayElementsMap(kind, native_context);
3782 AllocationSiteMode allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
3783 if (mode == DONT_OVERRIDE) {
3784 allocation_site_mode = AllocationSite::ShouldTrack(kind)
3785 ? TRACK_ALLOCATION_SITE
3786 : DONT_TRACK_ALLOCATION_SITE;
3789 Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
3790 Node* allocation_site = Parameter(Descriptor::kAllocationSite);
3792 GenerateConstructor(context,
function, array_map, array_size, allocation_site,
3793 kind, allocation_site_mode);
3796 void ArrayBuiltinsAssembler::GenerateArrayNArgumentsConstructor(
3797 TNode<Context> context, TNode<JSFunction> target, TNode<Object> new_target,
3798 TNode<Int32T> argc, TNode<HeapObject> maybe_allocation_site) {
3802 CodeStubArguments args(
this, ChangeInt32ToIntPtr(argc));
3803 args.SetReceiver(target);
3807 argc = Int32Add(argc, Int32Constant(3));
3808 TailCallRuntime(Runtime::kNewArray, argc, context, new_target,
3809 maybe_allocation_site);
3812 TF_BUILTIN(ArrayNArgumentsConstructor, ArrayBuiltinsAssembler) {
3813 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
3814 TNode<JSFunction> target = CAST(Parameter(Descriptor::kFunction));
3815 TNode<Int32T> argc =
3816 UncheckedCast<Int32T>(Parameter(Descriptor::kActualArgumentsCount));
3817 TNode<HeapObject> maybe_allocation_site =
3818 CAST(Parameter(Descriptor::kAllocationSite));
3820 GenerateArrayNArgumentsConstructor(context, target, target, argc,
3821 maybe_allocation_site);
3824 void ArrayBuiltinsAssembler::GenerateInternalArrayNoArgumentConstructor(
3825 ElementsKind kind) {
3826 typedef ArrayNoArgumentConstructorDescriptor Descriptor;
3827 TNode<Map> array_map =
3828 CAST(LoadObjectField(Parameter(Descriptor::kFunction),
3829 JSFunction::kPrototypeOrInitialMapOffset));
3830 TNode<JSArray> array = AllocateJSArray(
3831 kind, array_map, IntPtrConstant(JSArray::kPreallocatedArrayElements),
3836 void ArrayBuiltinsAssembler::GenerateInternalArraySingleArgumentConstructor(
3837 ElementsKind kind) {
3838 typedef ArraySingleArgumentConstructorDescriptor Descriptor;
3839 Node* context = Parameter(Descriptor::kContext);
3840 Node*
function = Parameter(Descriptor::kFunction);
3842 LoadObjectField(
function, JSFunction::kPrototypeOrInitialMapOffset);
3843 Node* array_size = Parameter(Descriptor::kArraySizeSmiParameter);
3844 Node* allocation_site = UndefinedConstant();
3846 GenerateConstructor(context,
function, array_map, array_size, allocation_site,
3847 kind, DONT_TRACK_ALLOCATION_SITE);
3850 #define GENERATE_ARRAY_CTOR(name, kind_camel, kind_caps, mode_camel, \ 3852 TF_BUILTIN(Array##name##Constructor_##kind_camel##_##mode_camel, \ 3853 ArrayBuiltinsAssembler) { \ 3854 GenerateArray##name##Constructor(kind_caps, mode_caps); \ 3858 GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS, DontOverride,
3860 GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
3862 GENERATE_ARRAY_CTOR(NoArgument, PackedSmi, PACKED_SMI_ELEMENTS,
3863 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3864 GENERATE_ARRAY_CTOR(NoArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
3865 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3866 GENERATE_ARRAY_CTOR(NoArgument, Packed, PACKED_ELEMENTS, DisableAllocationSites,
3867 DISABLE_ALLOCATION_SITES);
3868 GENERATE_ARRAY_CTOR(NoArgument, Holey, HOLEY_ELEMENTS, DisableAllocationSites,
3869 DISABLE_ALLOCATION_SITES);
3870 GENERATE_ARRAY_CTOR(NoArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
3871 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3872 GENERATE_ARRAY_CTOR(NoArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
3873 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3876 GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
3877 DontOverride, DONT_OVERRIDE);
3878 GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS, DontOverride,
3880 GENERATE_ARRAY_CTOR(SingleArgument, PackedSmi, PACKED_SMI_ELEMENTS,
3881 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3882 GENERATE_ARRAY_CTOR(SingleArgument, HoleySmi, HOLEY_SMI_ELEMENTS,
3883 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3884 GENERATE_ARRAY_CTOR(SingleArgument, Packed, PACKED_ELEMENTS,
3885 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3886 GENERATE_ARRAY_CTOR(SingleArgument, Holey, HOLEY_ELEMENTS,
3887 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3888 GENERATE_ARRAY_CTOR(SingleArgument, PackedDouble, PACKED_DOUBLE_ELEMENTS,
3889 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3890 GENERATE_ARRAY_CTOR(SingleArgument, HoleyDouble, HOLEY_DOUBLE_ELEMENTS,
3891 DisableAllocationSites, DISABLE_ALLOCATION_SITES);
3893 #undef GENERATE_ARRAY_CTOR 3895 #define GENERATE_INTERNAL_ARRAY_CTOR(name, kind_camel, kind_caps) \ 3896 TF_BUILTIN(InternalArray##name##Constructor_##kind_camel, \ 3897 ArrayBuiltinsAssembler) { \ 3898 GenerateInternalArray##name##Constructor(kind_caps); \ 3901 GENERATE_INTERNAL_ARRAY_CTOR(NoArgument, Packed, PACKED_ELEMENTS);
3902 GENERATE_INTERNAL_ARRAY_CTOR(NoArgument, Holey, HOLEY_ELEMENTS);
3903 GENERATE_INTERNAL_ARRAY_CTOR(SingleArgument, Packed, PACKED_ELEMENTS);
3904 GENERATE_INTERNAL_ARRAY_CTOR(SingleArgument, Holey, HOLEY_ELEMENTS);
3906 #undef GENERATE_INTERNAL_ARRAY_CTOR