Commit f2695702 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[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/956073Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51871}
parent 1adc4a66
...@@ -606,7 +606,6 @@ action("js2c") { ...@@ -606,7 +606,6 @@ action("js2c") {
"src/js/array.js", "src/js/array.js",
"src/js/typedarray.js", "src/js/typedarray.js",
"src/js/messages.js", "src/js/messages.js",
"src/js/spread.js",
"src/debug/mirrors.js", "src/debug/mirrors.js",
"src/debug/debug.js", "src/debug/debug.js",
"src/debug/liveedit.js", "src/debug/liveedit.js",
......
...@@ -268,16 +268,21 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs( ...@@ -268,16 +268,21 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructDoubleVarargs(
void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
Node* target, Node* new_target, Node* spread, Node* args_count, Node* target, Node* new_target, Node* spread, Node* args_count,
Node* context) { 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); 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. // 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 // Check that the Array.prototype hasn't been modified in a way that would
// affect iteration. // affect iteration.
...@@ -285,69 +290,62 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread( ...@@ -285,69 +290,62 @@ void CallOrConstructBuiltinsAssembler::CallOrConstructWithSpread(
DCHECK(isolate()->heap()->array_iterator_protector()->IsPropertyCell()); DCHECK(isolate()->heap()->array_iterator_protector()->IsPropertyCell());
GotoIf(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), GotoIf(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
SmiConstant(Isolate::kProtectorInvalid)), SmiConstant(Isolate::kProtectorInvalid)),
&if_runtime); &if_generic);
Node* kind = LoadMapElementsKind(spread_map);
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);
GotoIf(Int32GreaterThan(kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), // The fast-path accesses the {spread} elements directly.
&if_runtime); var_length.Bind(
Branch(Word32And(kind, Int32Constant(1)), &if_holey, &if_done); LoadAndUntagToWord32ObjectField(spread, JSArray::kLengthOffset));
var_elements.Bind(LoadObjectField(spread, JSArray::kElementsOffset));
// Check the NoElementsProtector cell for holey arrays. // Check elements kind of {spread}.
BIND(&if_holey); Node* spread_kind = LoadMapElementsKind(spread_map);
{ Branch(IsNoElementsProtectorCellInvalid(), &if_runtime, &if_done); } GotoIf(Int32LessThan(spread_kind, Int32Constant(PACKED_DOUBLE_ELEMENTS)),
&if_smiorobject);
Branch(Int32GreaterThan(spread_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
&if_generic, &if_double);
BIND(&if_runtime); BIND(&if_generic);
{ {
Node* spread_iterable = LoadContextElement(LoadNativeContext(context), Label if_iterator_fn_not_callable(this, Label::kDeferred);
Context::SPREAD_ITERABLE_INDEX); Node* iterator_fn = GetProperty(context, spread, IteratorSymbolConstant());
spread_result.Bind(CallJS(CodeFactory::Call(isolate()), context, GotoIf(TaggedIsSmi(iterator_fn), &if_iterator_fn_not_callable);
spread_iterable, UndefinedConstant(), spread)); GotoIfNot(IsCallable(iterator_fn), &if_iterator_fn_not_callable);
CSA_ASSERT(this, IsJSArray(spread_result.value())); Node* list =
Goto(&if_done); 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. Node* const elements = var_elements.value();
Label if_not_double(this), if_double(this); Node* const length = var_length.value();
Node* elements =
LoadObjectField(spread_result.value(), JSArray::kElementsOffset);
Node* length = LoadAndUntagToWord32ObjectField(spread_result.value(),
JSArray::kLengthOffset);
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) { if (new_target == nullptr) {
Callable callable = CodeFactory::CallVarargs(isolate()); Callable callable = CodeFactory::CallVarargs(isolate());
TailCallStub(callable, context, target, args_count, elements, length); TailCallStub(callable, context, target, args_count, elements, length);
} else { } else {
Callable callable = CodeFactory::ConstructVarargs(isolate()); Callable callable = CodeFactory::ConstructVarargs(isolate());
TailCallStub(callable, context, target, new_target, args_count, TailCallStub(callable, context, target, new_target, args_count, elements,
elements, length); length);
} }
} }
BIND(&if_double); BIND(&if_double);
{ {
Node* const elements = var_elements.value();
Node* const length = var_length.value();
CallOrConstructDoubleVarargs(target, new_target, elements, length, CallOrConstructDoubleVarargs(target, new_target, elements, length,
args_count, context, kind); args_count, context, spread_kind);
}
} }
} }
......
...@@ -45,6 +45,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; ...@@ -45,6 +45,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \ V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap) \
V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \ V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol) \
V(HeapNumberMap, heap_number_map, HeapNumberMap) \ V(HeapNumberMap, heap_number_map, HeapNumberMap) \
V(iterator_symbol, iterator_symbol, IteratorSymbol) \
V(length_string, length_string, LengthString) \ V(length_string, length_string, LengthString) \
V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \ V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap) \
V(MetaMap, meta_map, MetaMap) \ V(MetaMap, meta_map, MetaMap) \
......
...@@ -57,7 +57,6 @@ enum ContextLookupFlags { ...@@ -57,7 +57,6 @@ enum ContextLookupFlags {
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \ V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \ V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_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_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \ V(MATH_POW_INDEX, JSFunction, math_pow) \
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \ V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
......
// 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,
]);
})
...@@ -618,9 +618,6 @@ TEST(BytecodeGraphBuilderCallRuntime) { ...@@ -618,9 +618,6 @@ TEST(BytecodeGraphBuilderCallRuntime) {
{factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}}, {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
{"function f(arg0) { return %Add(arg0, 2) }\nf(1)", {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
{factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}}, {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++) { for (size_t i = 0; i < arraysize(snippets); i++) {
......
...@@ -65,24 +65,3 @@ constant pool: [ ...@@ -65,24 +65,3 @@ constant pool: [
handlers: [ 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: [
]
...@@ -601,9 +601,6 @@ TEST(CallRuntime) { ...@@ -601,9 +601,6 @@ TEST(CallRuntime) {
"function f() { return %Add(1, 2) }\n" "function f() { return %Add(1, 2) }\n"
"f();\n", "f();\n",
"function f() { return %spread_iterable([1]) }\n"
"f();\n",
}; };
CHECK(CompareTexts(BuildActual(printer, snippets), CHECK(CompareTexts(BuildActual(printer, snippets),
......
...@@ -193,7 +193,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -193,7 +193,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CallUndefinedReceiver(reg, pair, 1) .CallUndefinedReceiver(reg, pair, 1)
.CallRuntime(Runtime::kIsArray, reg) .CallRuntime(Runtime::kIsArray, reg)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair) .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); .CallWithSpread(reg, reg_list, 1);
// Emit binary operator invocations. // Emit binary operator invocations.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment