| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include 'src/builtins/builtins-iterator-gen.h' |
| |
| namespace iterator { |
| // Returned from IteratorBuiltinsAssembler::GetIterator(). |
| @export |
| struct IteratorRecord { |
| // iteratorRecord.[[Iterator]] |
| object: JSReceiver; |
| |
| // iteratorRecord.[[NextMethod]] |
| next: JSAny; |
| } |
| |
| extern macro IteratorBuiltinsAssembler::FastIterableToList( |
| implicit context: Context)(JSAny): JSArray labels Slow; |
| |
| extern macro IteratorBuiltinsAssembler::GetIteratorMethod( |
| implicit context: Context)(JSAny): JSAny; |
| extern macro IteratorBuiltinsAssembler::GetIterator(implicit context: Context)( |
| JSAny): IteratorRecord; |
| extern macro IteratorBuiltinsAssembler::GetIterator(implicit context: Context)( |
| JSAny, JSAny): IteratorRecord; |
| |
| extern macro IteratorBuiltinsAssembler::IteratorStep(implicit context: Context)( |
| IteratorRecord): JSReceiver |
| labels Done; |
| extern macro IteratorBuiltinsAssembler::IteratorStep(implicit context: Context)( |
| IteratorRecord, Map): JSReceiver |
| labels Done; |
| |
| extern macro IteratorBuiltinsAssembler::IteratorValue( |
| implicit context: Context)(JSReceiver): JSAny; |
| extern macro IteratorBuiltinsAssembler::IteratorValue( |
| implicit context: Context)(JSReceiver, Map): JSAny; |
| |
| extern macro IteratorBuiltinsAssembler::IterableToList( |
| implicit context: Context)(JSAny, JSAny): JSArray; |
| |
| extern macro IteratorBuiltinsAssembler::StringListFromIterable( |
| implicit context: Context)(JSAny): JSArray; |
| |
| extern builtin IterableToListWithSymbolLookup(implicit context: Context)(JSAny): |
| JSArray; |
| extern builtin IterableToFixedArrayWithSymbolLookupSlow( |
| implicit context: Context)(JSAny): FixedArray; |
| |
| transitioning builtin GetIteratorWithFeedback( |
| context: Context, receiver: JSAny, loadSlot: TaggedIndex, |
| callSlot: TaggedIndex, |
| maybeFeedbackVector: Undefined|FeedbackVector): JSAny { |
| // TODO(v8:9891): Remove this assert once all callers are ported to Torque. |
| // This assert ensures correctness of maybeFeedbackVector's type which can |
| // be easily broken for calls from CSA. |
| assert( |
| IsUndefined(maybeFeedbackVector) || |
| Is<FeedbackVector>(maybeFeedbackVector)); |
| let iteratorMethod: JSAny; |
| typeswitch (maybeFeedbackVector) { |
| case (Undefined): { |
| iteratorMethod = GetProperty(receiver, IteratorSymbolConstant()); |
| } |
| case (feedback: FeedbackVector): { |
| iteratorMethod = LoadIC( |
| context, receiver, IteratorSymbolConstant(), loadSlot, feedback); |
| } |
| } |
| // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. |
| const callSlotSmi: Smi = TaggedIndexToSmi(callSlot); |
| return CallIteratorWithFeedback( |
| context, receiver, iteratorMethod, callSlotSmi, maybeFeedbackVector); |
| } |
| |
| transitioning builtin CallIteratorWithFeedback( |
| context: Context, receiver: JSAny, iteratorMethod: JSAny, callSlot: Smi, |
| feedback: Undefined|FeedbackVector): JSAny { |
| const callSlotUnTagged: uintptr = Unsigned(SmiUntag(callSlot)); |
| ic::CollectCallFeedback(iteratorMethod, context, feedback, callSlotUnTagged); |
| const iteratorCallable: Callable = Cast<Callable>(iteratorMethod) |
| otherwise ThrowCalledNonCallable(iteratorMethod); |
| return Call(context, iteratorCallable, receiver); |
| } |
| |
| // https://tc39.es/ecma262/#sec-iteratorclose |
| @export |
| transitioning macro IteratorCloseOnException(implicit context: Context)( |
| iterator: IteratorRecord) { |
| try { |
| // 4. Let innerResult be GetMethod(iterator, "return"). |
| const method = GetProperty(iterator.object, kReturnString); |
| |
| // 5. If innerResult.[[Type]] is normal, then |
| // a. Let return be innerResult.[[Value]]. |
| // b. If return is undefined, return Completion(completion). |
| if (method == Undefined || method == Null) return; |
| |
| // c. Set innerResult to Call(return, iterator). |
| // If an exception occurs, the original exception remains bound |
| Call(context, method, iterator.object); |
| } catch (_e) { |
| // Swallow the exception. |
| } |
| |
| // (If completion.[[Type]] is throw) return Completion(completion). |
| } |
| } |