5 #include "src/builtins/builtins-iterator-gen.h" 6 #include "src/builtins/growable-fixed-array-gen.h" 8 #include "src/builtins/builtins-collections-gen.h" 9 #include "src/builtins/builtins-string-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/heap/factory-inl.h" 14 #include "torque-generated/builtins-base-from-dsl-gen.h" 19 typedef IteratorBuiltinsFromDSLAssembler::IteratorRecord IteratorRecord;
23 TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,
25 return GetProperty(context,
object, factory()->iterator_symbol());
28 IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
31 Variable* exception) {
32 Node* method = GetIteratorMethod(context,
object);
33 return GetIterator(context,
object, method, if_exception, exception);
36 IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
40 Variable* exception) {
41 GotoIfException(method, if_exception, exception);
43 Label if_not_callable(
this, Label::kDeferred), if_callable(
this);
44 GotoIf(TaggedIsSmi(method), &if_not_callable);
45 Branch(IsCallable(method), &if_callable, &if_not_callable);
47 BIND(&if_not_callable);
49 Node* ret = CallRuntime(Runtime::kThrowIteratorError, context,
object);
50 GotoIfException(ret, if_exception, exception);
56 Callable callable = CodeFactory::Call(isolate());
57 Node* iterator = CallJS(callable, context, method,
object);
58 GotoIfException(iterator, if_exception, exception);
60 Label get_next(
this), if_notobject(
this, Label::kDeferred);
61 GotoIf(TaggedIsSmi(iterator), &if_notobject);
62 Branch(IsJSReceiver(iterator), &get_next, &if_notobject);
66 Node* ret = CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context);
67 GotoIfException(ret, if_exception, exception);
72 Node*
const next = GetProperty(context, iterator, factory()->next_string());
73 GotoIfException(next, if_exception, exception);
75 return IteratorRecord{TNode<JSReceiver>::UncheckedCast(iterator),
76 TNode<Object>::UncheckedCast(next)};
80 TNode<Object> IteratorBuiltinsAssembler::IteratorStep(
81 Node* context,
const IteratorRecord& iterator, Label* if_done,
82 Node* fast_iterator_result_map, Label* if_exception, Variable* exception) {
83 DCHECK_NOT_NULL(if_done);
85 Callable callable = CodeFactory::Call(isolate());
86 Node* result = CallJS(callable, context, iterator.next, iterator.object);
87 GotoIfException(result, if_exception, exception);
90 Label if_notobject(
this, Label::kDeferred), return_result(
this);
91 GotoIf(TaggedIsSmi(result), &if_notobject);
92 Node* result_map = LoadMap(result);
94 if (fast_iterator_result_map !=
nullptr) {
96 Label if_generic(
this);
99 GotoIfNot(WordEqual(result_map, fast_iterator_result_map), &if_generic);
103 Node* done = LoadObjectField(result, JSIteratorResult::kDoneOffset);
104 BranchIfToBooleanIsTrue(done, if_done, &return_result);
112 GotoIfNot(IsJSReceiverMap(result_map), &if_notobject);
116 Node* done = GetProperty(context, result, factory()->done_string());
117 GotoIfException(done, if_exception, exception);
118 BranchIfToBooleanIsTrue(done, if_done, &return_result);
124 CallRuntime(Runtime::kThrowIteratorResultNotAnObject, context, result);
125 GotoIfException(ret, if_exception, exception);
129 BIND(&return_result);
130 return UncheckedCast<Object>(result);
133 Node* IteratorBuiltinsAssembler::IteratorValue(Node* context, Node* result,
134 Node* fast_iterator_result_map,
136 Variable* exception) {
137 CSA_ASSERT(
this, IsJSReceiver(result));
140 VARIABLE(var_value, MachineRepresentation::kTagged);
141 if (fast_iterator_result_map !=
nullptr) {
143 Label if_generic(
this);
144 Node* map = LoadMap(result);
145 GotoIfNot(WordEqual(map, fast_iterator_result_map), &if_generic);
146 var_value.Bind(LoadObjectField(result, JSIteratorResult::kValueOffset));
154 Node* value = GetProperty(context, result, factory()->value_string());
155 GotoIfException(value, if_exception, exception);
156 var_value.Bind(value);
161 return var_value.value();
164 void IteratorBuiltinsAssembler::IteratorCloseOnException(
165 Node* context,
const IteratorRecord& iterator, Label* if_exception,
166 Variable* exception) {
170 DCHECK((if_exception !=
nullptr && exception !=
nullptr));
171 CSA_ASSERT(
this, IsNotTheHole(exception->value()));
172 CSA_ASSERT(
this, IsJSReceiver(iterator.object));
176 GetProperty(context, iterator.object, factory()->return_string());
177 GotoIfException(method, if_exception, exception);
180 GotoIf(Word32Or(IsUndefined(method), IsNull(method)), if_exception);
186 CallJS(CodeFactory::Call(isolate()), context, method, iterator.object);
187 GotoIfException(inner_result, if_exception,
nullptr);
194 void IteratorBuiltinsAssembler::IteratorCloseOnException(
195 Node* context,
const IteratorRecord& iterator, TNode<Object> exception) {
196 Label rethrow(
this, Label::kDeferred);
197 TVARIABLE(Object, exception_variable, exception);
198 IteratorCloseOnException(context, iterator, &rethrow, &exception_variable);
201 CallRuntime(Runtime::kReThrow, context, exception_variable.value());
205 TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
206 TNode<Context> context, TNode<Object> iterable, TNode<Object> iterator_fn) {
208 IteratorRecord iterator_record = GetIterator(context, iterable, iterator_fn);
211 GrowableFixedArray values(state());
213 Variable* vars[] = {values.var_array(), values.var_length(),
214 values.var_capacity()};
215 Label loop_start(
this, 3, vars), done(
this);
222 TNode<Object> next = IteratorStep(context, iterator_record, &done);
225 TNode<Object> next_value = CAST(IteratorValue(context, next));
227 values.Push(next_value);
232 return values.ToJSArray(context);
235 TF_BUILTIN(IterableToList, IteratorBuiltinsAssembler) {
236 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
237 TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
238 TNode<Object> iterator_fn = CAST(Parameter(Descriptor::kIteratorFn));
240 Return(IterableToList(context, iterable, iterator_fn));
252 TF_BUILTIN(IterableToListMayPreserveHoles, IteratorBuiltinsAssembler) {
253 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
254 TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
255 TNode<Object> iterator_fn = CAST(Parameter(Descriptor::kIteratorFn));
257 Label slow_path(
this);
259 GotoIfNot(IsFastJSArrayWithNoCustomIteration(context, iterable), &slow_path);
262 TailCallBuiltin(Builtins::kCloneFastJSArray, context, iterable);
265 TailCallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn);
268 void IteratorBuiltinsAssembler::FastIterableToList(
269 TNode<Context> context, TNode<Object> iterable,
270 TVariable<Object>* var_result, Label* slow) {
271 Label done(
this), check_string(
this), check_map(
this), check_set(
this);
273 GotoIfNot(IsFastJSArrayWithNoCustomIteration(context, iterable),
278 CallBuiltin(Builtins::kCloneFastJSArrayFillingHoles, context, iterable);
283 Label string_maybe_fast_call(
this);
284 StringBuiltinsAssembler string_assembler(state());
285 string_assembler.BranchIfStringPrimitiveWithNoCustomIteration(
286 iterable, context, &string_maybe_fast_call, &check_map);
288 BIND(&string_maybe_fast_call);
289 TNode<IntPtrT>
const length = LoadStringLengthAsWord(CAST(iterable));
292 IntPtrGreaterThan(length, IntPtrConstant(JSArray::kMaxFastArrayLength)),
294 *var_result = CallBuiltin(Builtins::kStringToList, context, iterable);
300 Label map_fast_call(
this);
301 BranchIfIterableWithOriginalKeyOrValueMapIterator(
302 state(), iterable, context, &map_fast_call, &check_set);
304 BIND(&map_fast_call);
305 *var_result = CallBuiltin(Builtins::kMapIteratorToList, context, iterable);
311 Label set_fast_call(
this);
312 BranchIfIterableWithOriginalValueSetIterator(state(), iterable, context,
313 &set_fast_call, slow);
315 BIND(&set_fast_call);
317 CallBuiltin(Builtins::kSetOrSetIteratorToList, context, iterable);
335 TF_BUILTIN(IterableToListWithSymbolLookup, IteratorBuiltinsAssembler) {
336 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
337 TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
339 Label slow_path(
this);
341 GotoIfForceSlowPath(&slow_path);
343 TVARIABLE(Object, var_result);
344 FastIterableToList(context, iterable, &var_result, &slow_path);
345 Return(var_result.value());
349 TNode<Object> iterator_fn = GetIteratorMethod(context, iterable);
350 TailCallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn);