blob: b8f1fb27ac384c105de566f1351fb4e9fe5211c5 [file] [log] [blame]
// Copyright 2021 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"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/growable-fixed-array-gen.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/objects/js-temporal-objects-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
namespace v8 {
namespace internal {
class TemporalBuiltinsAssembler : public IteratorBuiltinsAssembler {
public:
explicit TemporalBuiltinsAssembler(compiler::CodeAssemblerState* state)
: IteratorBuiltinsAssembler(state) {}
// For the use inside Temporal GetPossibleInstantFor
TNode<FixedArray> TemporalInstantFixedArrayFromIterable(
TNode<Context> context, TNode<Object> iterable);
};
// #sec-iterabletolistoftype
TNode<FixedArray>
TemporalBuiltinsAssembler::TemporalInstantFixedArrayFromIterable(
TNode<Context> context, TNode<Object> iterable) {
GrowableFixedArray list(state());
Label done(this);
// 1. If iterable is undefined, then
// a. Return a new empty List.
GotoIf(IsUndefined(iterable), &done);
// 2. Let iteratorRecord be ? GetIterator(items).
IteratorRecord iterator_record = GetIterator(context, iterable);
// 3. Let list be a new empty List.
Label loop_start(this,
{list.var_array(), list.var_length(), list.var_capacity()});
Goto(&loop_start);
// 4. Let next be true.
// 5. Repeat, while next is not false
Label if_isnottemporalinstant(this, Label::kDeferred),
if_exception(this, Label::kDeferred);
BIND(&loop_start);
{
// a. Set next to ? IteratorStep(iteratorRecord).
TNode<JSReceiver> next = IteratorStep(context, iterator_record, &done);
// b. If next is not false, then
// i. Let nextValue be ? IteratorValue(next).
TNode<Object> next_value = IteratorValue(context, next);
// ii. If Type(nextValue) is not Object or nextValue does not have an
// [[InitializedTemporalInstant]] internal slot
GotoIf(TaggedIsSmi(next_value), &if_isnottemporalinstant);
TNode<Uint16T> next_value_type = LoadInstanceType(CAST(next_value));
GotoIfNot(IsTemporalInstantInstanceType(next_value_type),
&if_isnottemporalinstant);
// iii. Append nextValue to the end of the List list.
list.Push(next_value);
Goto(&loop_start);
// 5.b.ii
BIND(&if_isnottemporalinstant);
{
// 1. Let error be ThrowCompletion(a newly created TypeError object).
TVARIABLE(Object, var_exception);
{
compiler::ScopedExceptionHandler handler(this, &if_exception,
&var_exception);
CallRuntime(Runtime::kThrowTypeError, context,
SmiConstant(MessageTemplate::kIterableYieldedNonString),
next_value);
}
Unreachable();
// 2. Return ? IteratorClose(iteratorRecord, error).
BIND(&if_exception);
IteratorCloseOnException(context, iterator_record);
CallRuntime(Runtime::kReThrow, context, var_exception.value());
Unreachable();
}
}
BIND(&done);
return list.ToFixedArray();
}
TF_BUILTIN(TemporalInstantFixedArrayFromIterable, TemporalBuiltinsAssembler) {
auto context = Parameter<Context>(Descriptor::kContext);
auto iterable = Parameter<Object>(Descriptor::kIterable);
Return(TemporalInstantFixedArrayFromIterable(context, iterable));
}
} // namespace internal
} // namespace v8