1 // Copyright 2021 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/builtins/builtins-iterator-gen.h"
6 #include "src/builtins/builtins-utils-gen.h"
7 #include "src/builtins/growable-fixed-array-gen.h"
8 #include "src/codegen/code-stub-assembler.h"
9 #include "src/objects/js-temporal-objects-inl.h"
10 #include "src/objects/objects-inl.h"
11 #include "src/objects/objects.h"
12
13 namespace v8 {
14 namespace internal {
15
16 class TemporalBuiltinsAssembler : public IteratorBuiltinsAssembler {
17 public:
TemporalBuiltinsAssembler(compiler::CodeAssemblerState * state)18 explicit TemporalBuiltinsAssembler(compiler::CodeAssemblerState* state)
19 : IteratorBuiltinsAssembler(state) {}
20
21 // For the use inside Temporal GetPossibleInstantFor
22 TNode<FixedArray> TemporalInstantFixedArrayFromIterable(
23 TNode<Context> context, TNode<Object> iterable);
24 };
25
26 // #sec-iterabletolistoftype
27 TNode<FixedArray>
TemporalInstantFixedArrayFromIterable(TNode<Context> context,TNode<Object> iterable)28 TemporalBuiltinsAssembler::TemporalInstantFixedArrayFromIterable(
29 TNode<Context> context, TNode<Object> iterable) {
30 GrowableFixedArray list(state());
31 Label done(this);
32 // 1. If iterable is undefined, then
33 // a. Return a new empty List.
34 GotoIf(IsUndefined(iterable), &done);
35
36 // 2. Let iteratorRecord be ? GetIterator(items).
37 IteratorRecord iterator_record = GetIterator(context, iterable);
38
39 // 3. Let list be a new empty List.
40
41 Label loop_start(this,
42 {list.var_array(), list.var_length(), list.var_capacity()});
43 Goto(&loop_start);
44 // 4. Let next be true.
45 // 5. Repeat, while next is not false
46 Label if_isnottemporalinstant(this, Label::kDeferred),
47 if_exception(this, Label::kDeferred);
48 BIND(&loop_start);
49 {
50 // a. Set next to ? IteratorStep(iteratorRecord).
51 TNode<JSReceiver> next = IteratorStep(context, iterator_record, &done);
52 // b. If next is not false, then
53 // i. Let nextValue be ? IteratorValue(next).
54 TNode<Object> next_value = IteratorValue(context, next);
55 // ii. If Type(nextValue) is not Object or nextValue does not have an
56 // [[InitializedTemporalInstant]] internal slot
57 GotoIf(TaggedIsSmi(next_value), &if_isnottemporalinstant);
58 TNode<Uint16T> next_value_type = LoadInstanceType(CAST(next_value));
59 GotoIfNot(IsTemporalInstantInstanceType(next_value_type),
60 &if_isnottemporalinstant);
61 // iii. Append nextValue to the end of the List list.
62 list.Push(next_value);
63 Goto(&loop_start);
64 // 5.b.ii
65 BIND(&if_isnottemporalinstant);
66 {
67 // 1. Let error be ThrowCompletion(a newly created TypeError object).
68 TVARIABLE(Object, var_exception);
69 {
70 compiler::ScopedExceptionHandler handler(this, &if_exception,
71 &var_exception);
72 CallRuntime(Runtime::kThrowTypeError, context,
73 SmiConstant(MessageTemplate::kIterableYieldedNonString),
74 next_value);
75 }
76 Unreachable();
77
78 // 2. Return ? IteratorClose(iteratorRecord, error).
79 BIND(&if_exception);
80 IteratorCloseOnException(context, iterator_record);
81 CallRuntime(Runtime::kReThrow, context, var_exception.value());
82 Unreachable();
83 }
84 }
85
86 BIND(&done);
87 return list.ToFixedArray();
88 }
89
TF_BUILTIN(TemporalInstantFixedArrayFromIterable,TemporalBuiltinsAssembler)90 TF_BUILTIN(TemporalInstantFixedArrayFromIterable, TemporalBuiltinsAssembler) {
91 auto context = Parameter<Context>(Descriptor::kContext);
92 auto iterable = Parameter<Object>(Descriptor::kIterable);
93
94 Return(TemporalInstantFixedArrayFromIterable(context, iterable));
95 }
96
97 } // namespace internal
98 } // namespace v8
99