1// Copyright 2018 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
7namespace iterator {
8// Returned from IteratorBuiltinsAssembler::GetIterator().
9@export
10struct IteratorRecord {
11  // iteratorRecord.[[Iterator]]
12  object: JSReceiver;
13
14  // iteratorRecord.[[NextMethod]]
15  next: JSAny;
16}
17
18extern macro IteratorBuiltinsAssembler::FastIterableToList(
19    implicit context: Context)(JSAny): JSArray labels Slow;
20
21extern macro IteratorBuiltinsAssembler::GetIteratorMethod(
22    implicit context: Context)(JSAny): JSAny;
23extern macro IteratorBuiltinsAssembler::GetIterator(implicit context: Context)(
24    JSAny): IteratorRecord;
25extern macro IteratorBuiltinsAssembler::GetIterator(implicit context: Context)(
26    JSAny, JSAny): IteratorRecord;
27
28extern macro IteratorBuiltinsAssembler::IteratorStep(implicit context: Context)(
29    IteratorRecord): JSReceiver
30    labels Done;
31extern macro IteratorBuiltinsAssembler::IteratorStep(implicit context: Context)(
32    IteratorRecord, Map): JSReceiver
33    labels Done;
34
35extern macro IteratorBuiltinsAssembler::IteratorValue(
36    implicit context: Context)(JSReceiver): JSAny;
37extern macro IteratorBuiltinsAssembler::IteratorValue(
38    implicit context: Context)(JSReceiver, Map): JSAny;
39
40extern macro IteratorBuiltinsAssembler::IterableToList(
41    implicit context: Context)(JSAny, JSAny): JSArray;
42
43extern macro IteratorBuiltinsAssembler::StringListFromIterable(
44    implicit context: Context)(JSAny): JSArray;
45
46extern builtin IterableToListWithSymbolLookup(implicit context: Context)(JSAny):
47    JSArray;
48extern builtin IterableToFixedArrayWithSymbolLookupSlow(
49    implicit context: Context)(JSAny): FixedArray;
50
51transitioning builtin GetIteratorWithFeedback(
52    context: Context, receiver: JSAny, loadSlot: TaggedIndex,
53    callSlot: TaggedIndex,
54    maybeFeedbackVector: Undefined|FeedbackVector): JSAny {
55  // TODO(v8:9891): Remove this assert once all callers are ported to Torque.
56  // This assert ensures correctness of maybeFeedbackVector's type which can
57  // be easily broken for calls from CSA.
58  assert(
59      IsUndefined(maybeFeedbackVector) ||
60      Is<FeedbackVector>(maybeFeedbackVector));
61  let iteratorMethod: JSAny;
62  typeswitch (maybeFeedbackVector) {
63    case (Undefined): {
64      iteratorMethod = GetProperty(receiver, IteratorSymbolConstant());
65    }
66    case (feedback: FeedbackVector): {
67      iteratorMethod = LoadIC(
68          context, receiver, IteratorSymbolConstant(), loadSlot, feedback);
69    }
70  }
71  // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it.
72  const callSlotSmi: Smi = TaggedIndexToSmi(callSlot);
73  return CallIteratorWithFeedback(
74      context, receiver, iteratorMethod, callSlotSmi, maybeFeedbackVector);
75}
76
77transitioning builtin CallIteratorWithFeedback(
78    context: Context, receiver: JSAny, iteratorMethod: JSAny, callSlot: Smi,
79    feedback: Undefined|FeedbackVector): JSAny {
80  const callSlotUnTagged: uintptr = Unsigned(SmiUntag(callSlot));
81  ic::CollectCallFeedback(iteratorMethod, context, feedback, callSlotUnTagged);
82  const iteratorCallable: Callable = Cast<Callable>(iteratorMethod)
83      otherwise ThrowCalledNonCallable(iteratorMethod);
84  return Call(context, iteratorCallable, receiver);
85}
86
87// https://tc39.es/ecma262/#sec-iteratorclose
88@export
89transitioning macro IteratorCloseOnException(implicit context: Context)(
90    iterator: IteratorRecord) {
91  try {
92    // 4. Let innerResult be GetMethod(iterator, "return").
93    const method = GetProperty(iterator.object, kReturnString);
94
95    // 5. If innerResult.[[Type]] is normal, then
96    //   a. Let return be innerResult.[[Value]].
97    //   b. If return is undefined, return Completion(completion).
98    if (method == Undefined || method == Null) return;
99
100    //   c. Set innerResult to Call(return, iterator).
101    // If an exception occurs, the original exception remains bound
102    Call(context, method, iterator.object);
103  } catch (_e) {
104    // Swallow the exception.
105  }
106
107  // (If completion.[[Type]] is throw) return Completion(completion).
108}
109}
110