[builtins] Move IterableToList to iterator-gen
... So that this can be re-used in the intl code. Also, add a helper method that loads the iterator if it's not provided. Bug: v8:5751 Change-Id: Ifc1142a486b2cdf1c33a813c5446b206ad9f81ef Reviewed-on: https://chromium-review.googlesource.com/1156390 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#54819}
This commit is contained in:
parent
27cd5d0384
commit
43da50361c
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/builtins/builtins-iterator-gen.h"
|
||||
#include "src/builtins/growable-fixed-array-gen.h"
|
||||
|
||||
#include "src/heap/factory-inl.h"
|
||||
|
||||
@ -11,7 +12,7 @@ namespace internal {
|
||||
|
||||
using compiler::Node;
|
||||
|
||||
Node* IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,
|
||||
TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,
|
||||
Node* object) {
|
||||
return GetProperty(context, object, factory()->iterator_symbol());
|
||||
}
|
||||
@ -194,5 +195,68 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
|
||||
Unreachable();
|
||||
}
|
||||
|
||||
TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
|
||||
TNode<Context> context, TNode<Object> iterable, TNode<Object> iterator_fn) {
|
||||
Label fast_path(this), slow_path(this), done(this);
|
||||
|
||||
TVARIABLE(JSArray, created_list);
|
||||
|
||||
// This is a fast-path for ignoring the iterator.
|
||||
// TODO(petermarshall): Port IterableToListCanBeElided to CSA.
|
||||
Node* elided =
|
||||
CallRuntime(Runtime::kIterableToListCanBeElided, context, iterable);
|
||||
CSA_ASSERT(this, IsBoolean(elided));
|
||||
Branch(IsTrue(elided), &fast_path, &slow_path);
|
||||
|
||||
BIND(&fast_path);
|
||||
{
|
||||
TNode<JSArray> input_array = CAST(iterable);
|
||||
created_list = CAST(CloneFastJSArray(context, input_array));
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&slow_path);
|
||||
{
|
||||
// 1. Let iteratorRecord be ? GetIterator(items, method).
|
||||
IteratorRecord iterator_record =
|
||||
GetIterator(context, iterable, iterator_fn);
|
||||
|
||||
// 2. Let values be a new empty List.
|
||||
GrowableFixedArray values(state());
|
||||
|
||||
Variable* vars[] = {values.var_array(), values.var_length(),
|
||||
values.var_capacity()};
|
||||
Label loop_start(this, 3, vars), loop_end(this);
|
||||
Goto(&loop_start);
|
||||
// 3. Let next be true.
|
||||
// 4. Repeat, while next is not false
|
||||
BIND(&loop_start);
|
||||
{
|
||||
// a. Set next to ? IteratorStep(iteratorRecord).
|
||||
TNode<Object> next =
|
||||
CAST(IteratorStep(context, iterator_record, &loop_end));
|
||||
// b. If next is not false, then
|
||||
// i. Let nextValue be ? IteratorValue(next).
|
||||
TNode<Object> next_value = CAST(IteratorValue(context, next));
|
||||
// ii. Append nextValue to the end of the List values.
|
||||
values.Push(next_value);
|
||||
Goto(&loop_start);
|
||||
}
|
||||
BIND(&loop_end);
|
||||
|
||||
created_list = values.ToJSArray(context);
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&done);
|
||||
return created_list.value();
|
||||
}
|
||||
|
||||
TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
|
||||
TNode<Context> context, TNode<Object> iterable) {
|
||||
TNode<Object> method = GetIteratorMethod(context, iterable);
|
||||
return IterableToList(context, iterable, method);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -18,7 +18,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
// Returns object[Symbol.iterator].
|
||||
Node* GetIteratorMethod(Node* context, Node* object);
|
||||
TNode<Object> GetIteratorMethod(Node* context, Node* object);
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-getiterator --- never used for
|
||||
// @@asyncIterator.
|
||||
@ -53,6 +53,11 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
|
||||
Label* if_exception, Variable* exception);
|
||||
void IteratorCloseOnException(Node* context, const IteratorRecord& iterator,
|
||||
Variable* exception);
|
||||
|
||||
// /#sec-iterabletolist
|
||||
TNode<JSArray> IterableToList(TNode<Context> context, TNode<Object> iterable,
|
||||
TNode<Object> iterator_fn);
|
||||
TNode<JSArray> IterableToList(TNode<Context> context, TNode<Object> iterable);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -1647,44 +1647,6 @@ TF_BUILTIN(TypedArrayOf, TypedArrayBuiltinsAssembler) {
|
||||
"%TypedArray%.of");
|
||||
}
|
||||
|
||||
void TypedArrayBuiltinsAssembler::IterableToListSlowPath(
|
||||
TNode<Context> context, TNode<Object> iterable, TNode<Object> iterator_fn,
|
||||
Variable* created_list) {
|
||||
IteratorBuiltinsAssembler iterator_assembler(state());
|
||||
|
||||
// 1. Let iteratorRecord be ? GetIterator(items, method).
|
||||
IteratorRecord iterator_record =
|
||||
iterator_assembler.GetIterator(context, iterable, iterator_fn);
|
||||
|
||||
// 2. Let values be a new empty List.
|
||||
GrowableFixedArray values(state());
|
||||
|
||||
Variable* vars[] = {values.var_array(), values.var_length(),
|
||||
values.var_capacity()};
|
||||
Label loop_start(this, 3, vars), loop_end(this);
|
||||
Goto(&loop_start);
|
||||
// 3. Let next be true.
|
||||
// 4. Repeat, while next is not false
|
||||
BIND(&loop_start);
|
||||
{
|
||||
// a. Set next to ? IteratorStep(iteratorRecord).
|
||||
TNode<Object> next = CAST(
|
||||
iterator_assembler.IteratorStep(context, iterator_record, &loop_end));
|
||||
// b. If next is not false, then
|
||||
// i. Let nextValue be ? IteratorValue(next).
|
||||
TNode<Object> next_value =
|
||||
CAST(iterator_assembler.IteratorValue(context, next));
|
||||
// ii. Append nextValue to the end of the List values.
|
||||
values.Push(next_value);
|
||||
Goto(&loop_start);
|
||||
}
|
||||
BIND(&loop_end);
|
||||
|
||||
// 5. Return values.
|
||||
TNode<JSArray> js_array_values = values.ToJSArray(context);
|
||||
created_list->Bind(js_array_values);
|
||||
}
|
||||
|
||||
// This builtin always returns a new JSArray and is thus safe to use even in the
|
||||
// presence of code that may call back into user-JS.
|
||||
TF_BUILTIN(IterableToList, TypedArrayBuiltinsAssembler) {
|
||||
@ -1692,33 +1654,8 @@ TF_BUILTIN(IterableToList, TypedArrayBuiltinsAssembler) {
|
||||
TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
|
||||
TNode<Object> iterator_fn = CAST(Parameter(Descriptor::kIteratorFn));
|
||||
|
||||
Label fast_path(this), slow_path(this), done(this);
|
||||
|
||||
TVARIABLE(JSArray, created_list);
|
||||
|
||||
// This is a fast-path for ignoring the iterator.
|
||||
// TODO(petermarshall): Port IterableToListCanBeElided to CSA.
|
||||
Node* elided =
|
||||
CallRuntime(Runtime::kIterableToListCanBeElided, context, iterable);
|
||||
CSA_ASSERT(this, IsBoolean(elided));
|
||||
Branch(IsTrue(elided), &fast_path, &slow_path);
|
||||
|
||||
BIND(&fast_path);
|
||||
{
|
||||
TNode<JSArray> input_array = CAST(iterable);
|
||||
TNode<JSArray> new_array = CAST(CloneFastJSArray(context, input_array));
|
||||
created_list = new_array;
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&slow_path);
|
||||
{
|
||||
IterableToListSlowPath(context, iterable, iterator_fn, &created_list);
|
||||
Goto(&done);
|
||||
}
|
||||
|
||||
BIND(&done);
|
||||
Return(created_list.value());
|
||||
IteratorBuiltinsAssembler iterator_assembler(state());
|
||||
Return(iterator_assembler.IterableToList(context, iterable, iterator_fn));
|
||||
}
|
||||
|
||||
// ES6 #sec-%typedarray%.from
|
||||
|
@ -55,10 +55,6 @@ class TypedArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
|
||||
TNode<Map> map, TNode<Smi> length,
|
||||
TNode<Number> byte_offset);
|
||||
|
||||
void IterableToListSlowPath(TNode<Context> context, TNode<Object> iterable,
|
||||
TNode<Object> iterator_fn,
|
||||
Variable* created_list);
|
||||
|
||||
TNode<Map> LoadMapForType(TNode<JSTypedArray> array);
|
||||
TNode<UintPtrT> CalculateExternalPointer(TNode<UintPtrT> backing_store,
|
||||
TNode<Number> byte_offset);
|
||||
|
Loading…
Reference in New Issue
Block a user