Reduce duplication of generated code in IterableToList builtins.

This CL exposes IteratorBuiltinsAssembler::IterableToList as a builtin
to reduce generated code duplication. This follows up on CL 1201882.

Change-Id: I848e17bd1b6756de9e898e9d2f8c93d99699df07
Reviewed-on: https://chromium-review.googlesource.com/1206470
Commit-Queue: Hai Dang <dhai@google.com>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55641}
This commit is contained in:
Hai Dang 2018-09-05 11:18:27 +02:00 committed by Commit Bot
parent d84e9496d2
commit c0cf34104d
2 changed files with 16 additions and 9 deletions

View File

@ -646,6 +646,7 @@ namespace internal {
\ \
/* IterableToList */ \ /* IterableToList */ \
/* ES #sec-iterabletolist */ \ /* ES #sec-iterabletolist */ \
TFS(IterableToList, kIterable, kIteratorFn) \
TFS(IterableToListWithSymbolLookup, kIterable) \ TFS(IterableToListWithSymbolLookup, kIterable) \
TFS(IterableToListMayPreserveHoles, kIterable, kIteratorFn) \ TFS(IterableToListMayPreserveHoles, kIterable, kIteratorFn) \
\ \

View File

@ -7,6 +7,7 @@
#include "src/builtins/builtins-utils-gen.h" #include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h"
#include "src/heap/factory-inl.h" #include "src/heap/factory-inl.h"
namespace v8 { namespace v8 {
@ -226,6 +227,14 @@ TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
return values.ToJSArray(context); return values.ToJSArray(context);
} }
TF_BUILTIN(IterableToList, IteratorBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
TNode<Object> iterator_fn = CAST(Parameter(Descriptor::kIteratorFn));
Return(IterableToList(context, iterable, iterator_fn));
}
// This builtin always returns a new JSArray and is thus safe to use even in the // 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. This builtin will take the // presence of code that may call back into user-JS. This builtin will take the
// fast path if the iterable is a fast array and the Array prototype and the // fast path if the iterable is a fast array and the Array prototype and the
@ -234,7 +243,7 @@ TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
// will be copied to the new array, which is inconsistent with the behavior of // will be copied to the new array, which is inconsistent with the behavior of
// an actual iteration, where holes should be replaced with undefined (if the // an actual iteration, where holes should be replaced with undefined (if the
// prototype has no elements). To maintain the correct behavior for holey // prototype has no elements). To maintain the correct behavior for holey
// arrays, use the builtin IterableToListWithSymbolLookup. // arrays, use the builtins IterableToList or IterableToListWithSymbolLookup.
TF_BUILTIN(IterableToListMayPreserveHoles, IteratorBuiltinsAssembler) { TF_BUILTIN(IterableToListMayPreserveHoles, IteratorBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable)); TNode<Object> iterable = CAST(Parameter(Descriptor::kIterable));
@ -245,10 +254,10 @@ TF_BUILTIN(IterableToListMayPreserveHoles, IteratorBuiltinsAssembler) {
GotoIfNot(IsFastJSArrayWithNoCustomIteration(iterable, context), &slow_path); GotoIfNot(IsFastJSArrayWithNoCustomIteration(iterable, context), &slow_path);
// The fast path will copy holes to the new array. // The fast path will copy holes to the new array.
Return(CallBuiltin(Builtins::kCloneFastJSArray, context, iterable)); TailCallBuiltin(Builtins::kCloneFastJSArray, context, iterable);
BIND(&slow_path); BIND(&slow_path);
Return(IterableToList(context, iterable, iterator_fn)); TailCallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn);
} }
// This builtin uses the default Symbol.iterator for the iterator, and takes // This builtin uses the default Symbol.iterator for the iterator, and takes
@ -262,21 +271,18 @@ TF_BUILTIN(IterableToListWithSymbolLookup, IteratorBuiltinsAssembler) {
GotoIfNot(IsFastJSArrayWithNoCustomIteration(iterable, context), &slow_path); GotoIfNot(IsFastJSArrayWithNoCustomIteration(iterable, context), &slow_path);
// Here we are guaranteed that iterable is a fast JSArray with an original // Here we are guaranteed that iterable is a fast JSArray with an original
// iterator. // iterator.
Node* map = LoadMap(CAST(iterable)); Node* elements_kind = LoadMapElementsKind(LoadMap(CAST(iterable)));
Node* elements_kind = LoadMapElementsKind(map);
// Take the slow path if the array is holey. // Take the slow path if the array is holey.
GotoIf(IsHoleyFastElementsKind(elements_kind), &slow_path); GotoIf(IsHoleyFastElementsKind(elements_kind), &slow_path);
// This is a fast-path for ignoring the iterator. Here we are guaranteed that // This is a fast-path for ignoring the iterator. Here we are guaranteed that
// {iterable} is a fast _packed_ JSArray. // {iterable} is a fast _packed_ JSArray.
Return(CallBuiltin(Builtins::kCloneFastJSArray, context, iterable)); TailCallBuiltin(Builtins::kCloneFastJSArray, context, iterable);
BIND(&slow_path); BIND(&slow_path);
{ {
TNode<Object> iterator_fn = GetIteratorMethod(context, iterable); TNode<Object> iterator_fn = GetIteratorMethod(context, iterable);
// TODO(dhai): this is duplicating (generated) code with TailCallBuiltin(Builtins::kIterableToList, context, iterable, iterator_fn);
// IterableToListMayPreserveHoles. Make IterableToList a builtin.
Return(IterableToList(context, iterable, iterator_fn));
} }
} }