[cleanup] Drop spread.js for good.

Use IteratorToList to implement CallWithSpread and ConstructWithSpread
instead.

Bug: v8:7310
Change-Id: Ic1c44cc97914fa4fb92da8c568ac66f3ae78e520
Reviewed-on: https://chromium-review.googlesource.com/956073
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51871}
This commit is contained in:
Benedikt Meurer 2018-03-09 16:03:02 +01:00 committed by Commit Bot
parent 1adc4a66e8
commit f269570290
9 changed files with 100 additions and 164 deletions

View File

@ -606,7 +606,6 @@ action("js2c") {
"src/js/array.js",
"src/js/typedarray.js",
"src/js/messages.js",
"src/js/spread.js",
"src/debug/mirrors.js",
"src/debug/debug.js",
"src/debug/liveedit.js",

View File

@ -268,16 +268,21 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs(
void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
Node* target, Node* new_target, Node* spread, Node* args_count,
Node* context) {
Label if_done(this), if_holey(this), if_runtime(this, Label::kDeferred);
Label if_smiorobject(this), if_double(this),
if_generic(this, Label::kDeferred);
VARIABLE(spread_result, MachineRepresentation::kTagged, spread);
VARIABLE(var_length, MachineRepresentation::kWord32);
VARIABLE(var_elements, MachineRepresentation::kTagged);
GotoIf(TaggedIsSmi(spread), &if_runtime);
GotoIf(TaggedIsSmi(spread), &if_generic);
Node* spread_map = LoadMap(spread);
GotoIfNot(IsJSArrayMap(spread_map), &if_runtime);
GotoIfNot(IsJSArrayMap(spread_map), &if_generic);
// Check that we have the original Array.prototype.
GotoIfNot(IsPrototypeInitialArrayPrototype(context, spread_map), &if_runtime);
GotoIfNot(IsPrototypeInitialArrayPrototype(context, spread_map), &if_generic);
// Check that there are no elements on the Array.prototype chain.
GotoIf(IsNoElementsProtectorCellInvalid(), &if_generic);
// Check that the Array.prototype hasn't been modified in a way that would
// affect iteration.
@ -285,69 +290,62 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
DCHECK(isolate()->heap()->array_iterator_protector()->IsPropertyCell());
GotoIf(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
SmiConstant(Isolate::kProtectorInvalid)),
&if_runtime);
&if_generic);
Node* kind = LoadMapElementsKind(spread_map);
// The fast-path accesses the {spread} elements directly.
var_length.Bind(
LoadAndUntagToWord32ObjectField(spread, JSArray::kLengthOffset));
var_elements.Bind(LoadObjectField(spread, JSArray::kElementsOffset));
STATIC_ASSERT(PACKED_SMI_ELEMENTS == 0);
STATIC_ASSERT(HOLEY_SMI_ELEMENTS == 1);
STATIC_ASSERT(PACKED_ELEMENTS == 2);
STATIC_ASSERT(HOLEY_ELEMENTS == 3);
STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS == 4);
STATIC_ASSERT(HOLEY_DOUBLE_ELEMENTS == 5);
STATIC_ASSERT(LAST_FAST_ELEMENTS_KIND == HOLEY_DOUBLE_ELEMENTS);
// Check elements kind of {spread}.
Node* spread_kind = LoadMapElementsKind(spread_map);
GotoIf(Int32LessThan(spread_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
&if_smiorobject);
Branch(Int32GreaterThan(spread_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
&if_generic, &if_double);
GotoIf(Int32GreaterThan(kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
&if_runtime);
Branch(Word32And(kind, Int32Constant(1)), &if_holey, &if_done);
// Check the NoElementsProtector cell for holey arrays.
BIND(&if_holey);
{ Branch(IsNoElementsProtectorCellInvalid(), &if_runtime, &if_done); }
BIND(&if_runtime);
BIND(&if_generic);
{
Node* spread_iterable = LoadContextElement(LoadNativeContext(context),
Context::SPREAD_ITERABLE_INDEX);
spread_result.Bind(CallJS(CodeFactory::Call(isolate()), context,
spread_iterable, UndefinedConstant(), spread));
CSA_ASSERT(this, IsJSArray(spread_result.value()));
Goto(&if_done);
Label if_iterator_fn_not_callable(this, Label::kDeferred);
Node* iterator_fn = GetProperty(context, spread, IteratorSymbolConstant());
GotoIf(TaggedIsSmi(iterator_fn), &if_iterator_fn_not_callable);
GotoIfNot(IsCallable(iterator_fn), &if_iterator_fn_not_callable);
Node* list =
CallBuiltin(Builtins::kIterableToList, context, spread, iterator_fn);
CSA_ASSERT(this, IsJSArray(list));
CSA_ASSERT(this, Word32Equal(LoadMapElementsKind(LoadMap(list)),
Int32Constant(PACKED_ELEMENTS)));
var_length.Bind(
LoadAndUntagToWord32ObjectField(list, JSArray::kLengthOffset));
var_elements.Bind(LoadObjectField(list, JSArray::kElementsOffset));
Goto(&if_smiorobject);
BIND(&if_iterator_fn_not_callable);
ThrowTypeError(context, MessageTemplate::kIteratorSymbolNonCallable);
}
BIND(&if_done);
BIND(&if_smiorobject);
{
// The result from if_runtime can be an array of doubles.
Label if_not_double(this), if_double(this);
Node* elements =
LoadObjectField(spread_result.value(), JSArray::kElementsOffset);
Node* length = LoadAndUntagToWord32ObjectField(spread_result.value(),
JSArray::kLengthOffset);
Node* const elements = var_elements.value();
Node* const length = var_length.value();
Node* kind = LoadMapElementsKind(LoadMap(elements));
CSA_ASSERT(this, Int32LessThanOrEqual(
kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)));
Branch(Int32GreaterThan(kind, Int32Constant(HOLEY_ELEMENTS)), &if_double,
&if_not_double);
BIND(&if_not_double);
{
if (new_target == nullptr) {
Callable callable = CodeFactory::CallVarargs(isolate());
TailCallStub(callable, context, target, args_count, elements, length);
} else {
Callable callable = CodeFactory::ConstructVarargs(isolate());
TailCallStub(callable, context, target, new_target, args_count,
elements, length);
}
if (new_target == nullptr) {
Callable callable = CodeFactory::CallVarargs(isolate());
TailCallStub(callable, context, target, args_count, elements, length);
} else {
Callable callable = CodeFactory::ConstructVarargs(isolate());
TailCallStub(callable, context, target, new_target, args_count, elements,
length);
}
}
BIND(&if_double);
{
CallOrConstructDoubleVarargs(target, new_target, elements, length,
args_count, context, kind);
}
BIND(&if_double);
{
Node* const elements = var_elements.value();
Node* const length = var_length.value();
CallOrConstructDoubleVarargs(target, new_target, elements, length,
args_count, context, spread_kind);
}
}

View File

@ -22,48 +22,49 @@ class StubCache;
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
#define HEAP_CONSTANT_LIST(V) \
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \
V(BooleanMap, boolean_map, BooleanMap) \
V(CodeMap, code_map, CodeMap) \
V(EmptyPropertyDictionary, empty_property_dictionary, \
EmptyPropertyDictionary) \
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
V(EmptySlowElementDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
V(empty_string, empty_string, EmptyString) \
V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \
V(FalseValue, false_value, False) \
V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \
V(FixedArrayMap, fixed_array_map, FixedArrayMap) \
V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \
V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \
V(FunctionTemplateInfoMap, function_template_info_map, \
FunctionTemplateInfoMap) \
V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \
V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \
V(HeapNumberMap, heap_number_map, HeapNumberMap) \
V(length_string, length_string, LengthString) \
V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \
V(MetaMap, meta_map, MetaMap) \
V(MinusZeroValue, minus_zero_value, MinusZero) \
V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \
V(NanValue, nan_value, Nan) \
V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \
V(NullValue, null_value, Null) \
V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \
V(prototype_string, prototype_string, PrototypeString) \
V(SpeciesProtector, species_protector, SpeciesProtector) \
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
V(SymbolMap, symbol_map, SymbolMap) \
V(TheHoleValue, the_hole_value, TheHole) \
V(TrueValue, true_value, True) \
V(Tuple2Map, tuple2_map, Tuple2Map) \
V(Tuple3Map, tuple3_map, Tuple3Map) \
V(UndefinedValue, undefined_value, Undefined) \
V(WeakCellMap, weak_cell_map, WeakCellMap) \
#define HEAP_CONSTANT_LIST(V) \
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
V(AllocationSiteMap, allocation_site_map, AllocationSiteMap) \
V(BooleanMap, boolean_map, BooleanMap) \
V(CodeMap, code_map, CodeMap) \
V(EmptyPropertyDictionary, empty_property_dictionary, \
EmptyPropertyDictionary) \
V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray) \
V(EmptySlowElementDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
V(empty_string, empty_string, EmptyString) \
V(EmptyWeakCell, empty_weak_cell, EmptyWeakCell) \
V(FalseValue, false_value, False) \
V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap) \
V(FixedArrayMap, fixed_array_map, FixedArrayMap) \
V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap) \
V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap) \
V(FunctionTemplateInfoMap, function_template_info_map, \
FunctionTemplateInfoMap) \
V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \
V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \
V(HeapNumberMap, heap_number_map, HeapNumberMap) \
V(iterator_symbol, iterator_symbol, IteratorSymbol) \
V(length_string, length_string, LengthString) \
V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \
V(MetaMap, meta_map, MetaMap) \
V(MinusZeroValue, minus_zero_value, MinusZero) \
V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap) \
V(NanValue, nan_value, Nan) \
V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap) \
V(NullValue, null_value, Null) \
V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap) \
V(prototype_string, prototype_string, PrototypeString) \
V(SpeciesProtector, species_protector, SpeciesProtector) \
V(StoreHandler0Map, store_handler0_map, StoreHandler0Map) \
V(SymbolMap, symbol_map, SymbolMap) \
V(TheHoleValue, the_hole_value, TheHole) \
V(TrueValue, true_value, True) \
V(Tuple2Map, tuple2_map, Tuple2Map) \
V(Tuple3Map, tuple3_map, Tuple3Map) \
V(UndefinedValue, undefined_value, Undefined) \
V(WeakCellMap, weak_cell_map, WeakCellMap) \
V(SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfoMap)
// Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared

View File

@ -57,7 +57,6 @@ enum ContextLookupFlags {
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \

View File

@ -1,34 +0,0 @@
// Copyright 2015 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.
(function(global, utils) {
"use strict";
// -------------------------------------------------------------------
// Imports
var InternalArray = utils.InternalArray;
// -------------------------------------------------------------------
function SpreadIterable(collection) {
if (IS_NULL_OR_UNDEFINED(collection)) {
throw %make_type_error(kNotIterable, collection);
}
var args = new InternalArray();
for (var value of collection) {
args.push(value);
}
return args;
}
// ----------------------------------------------------------------------------
// Exports
%InstallToContext([
"spread_iterable", SpreadIterable,
]);
})

View File

@ -618,9 +618,6 @@ TEST(BytecodeGraphBuilderCallRuntime) {
{factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
{"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
{factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
{"function f(arg0) { return %spread_iterable(arg0).length }\nf([])",
{factory->NewNumberFromInt(3),
BytecodeGraphTester::NewObject("[1, 2, 3]")}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {

View File

@ -65,24 +65,3 @@ constant pool: [
handlers: [
]
---
snippet: "
function f() { return %spread_iterable([1]) }
f();
"
frame size: 1
parameter count: 1
bytecode array length: 12
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 15 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(0),
B(CallJSRuntime), U8(%spread_iterable), R(0), U8(1),
/* 43 S> */ B(Return),
]
constant pool: [
TUPLE2_TYPE,
]
handlers: [
]

View File

@ -601,9 +601,6 @@ TEST(CallRuntime) {
"function f() { return %Add(1, 2) }\n"
"f();\n",
"function f() { return %spread_iterable([1]) }\n"
"f();\n",
};
CHECK(CompareTexts(BuildActual(printer, snippets),

View File

@ -193,7 +193,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CallUndefinedReceiver(reg, pair, 1)
.CallRuntime(Runtime::kIsArray, reg)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair)
.CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg_list)
.CallJSRuntime(Context::OBJECT_IS_FROZEN, reg_list)
.CallWithSpread(reg, reg_list, 1);
// Emit binary operator invocations.