Commit 1eb0ef31 authored by mvstanton's avatar mvstanton Committed by Commit bot

[builtins] Improve performance of array.prototype.filter and map.

BUG=

Review-Url: https://codereview.chromium.org/2775503006
Cr-Commit-Position: refs/heads/master@{#44793}
parent 86ba4661
......@@ -3859,14 +3859,6 @@ void Genesis::InstallOneBuiltinFunction(Handle<Object> prototype,
void Genesis::InitializeGlobal_experimental_fast_array_builtins() {
if (!FLAG_experimental_fast_array_builtins) return;
{
Handle<JSFunction> array_constructor(native_context()->array_function());
Handle<Object> array_prototype(array_constructor->prototype(), isolate());
// Insert experimental fast Array builtins here.
InstallOneBuiltinFunction(array_prototype, "filter",
Builtins::kArrayFilter);
InstallOneBuiltinFunction(array_prototype, "map", Builtins::kArrayMap);
}
{
Handle<Object> typed_array_prototype(
native_context()->typed_array_prototype(), isolate());
......@@ -4355,6 +4347,12 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
// Add forEach to the context.
native_context()->set_array_for_each_iterator(*forEach);
// Install Array.prototype.filter
InstallArrayBuiltinFunction(proto, "filter", Builtins::kArrayFilter, 2);
// Install Array.prototype.map
InstallArrayBuiltinFunction(proto, "map", Builtins::kArrayMap, 2);
// Install Array.prototype.every
InstallArrayBuiltinFunction(proto, "every", Builtins::kArrayEvery, 2);
......
......@@ -137,13 +137,58 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
BIND(&true_continue);
// iii. If selected is true, then...
{
// 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
k_value);
Label after_work(this, &to_);
Node* kind = nullptr;
// 2. Increase to by 1.
to_.Bind(NumberInc(to_.value()));
Goto(&false_continue);
// If a() is a JSArray, we can have a fast path.
Label fast(this);
Label runtime(this);
Label object_push_pre(this), object_push(this), double_push(this);
BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
&fast, &runtime);
BIND(&fast);
{
kind = EnsureArrayPushable(a(), &runtime);
GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
&object_push_pre);
BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime);
Goto(&after_work);
}
BIND(&object_push_pre);
{
Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS),
&double_push, &object_push);
}
BIND(&object_push);
{
BuildAppendJSArray(FAST_ELEMENTS, a(), k_value, &runtime);
Goto(&after_work);
}
BIND(&double_push);
{
BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, a(), k_value, &runtime);
Goto(&after_work);
}
BIND(&runtime);
{
// 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
k_value);
Goto(&after_work);
}
BIND(&after_work);
{
// 2. Increase to by 1.
to_.Bind(NumberInc(to_.value()));
Goto(&false_continue);
}
}
BIND(&false_continue);
return a();
......@@ -160,8 +205,58 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
Label finished(this);
Node* kind = nullptr;
Node* elements = nullptr;
// If a() is a JSArray, we can have a fast path.
// mode is SMI_PARAMETERS because k has tagged representation.
ParameterMode mode = SMI_PARAMETERS;
Label fast(this);
Label runtime(this);
Label object_push_pre(this), object_push(this), double_push(this);
BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS,
&fast, &runtime);
BIND(&fast);
{
kind = EnsureArrayPushable(a(), &runtime);
elements = LoadElements(a());
GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
&object_push_pre);
TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k,
mappedValue);
Goto(&finished);
}
BIND(&object_push_pre);
{
Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push,
&object_push);
}
BIND(&object_push);
{
TryStoreArrayElement(FAST_ELEMENTS, mode, &runtime, elements, k,
mappedValue);
Goto(&finished);
}
BIND(&double_push);
{
TryStoreArrayElement(FAST_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
mappedValue);
Goto(&finished);
}
BIND(&runtime);
{
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
Goto(&finished);
}
BIND(&finished);
return a();
}
......@@ -575,7 +670,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
Node* o_map = LoadMap(o());
Node* bit_field2 = LoadMapBitField2(o_map);
Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS),
&maybe_double_elements, &fast_elements);
ParameterMode mode = OptimalParameterMode();
......@@ -591,8 +686,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
}
BIND(&maybe_double_elements);
Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)),
slow, &fast_double_elements);
Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_DOUBLE_ELEMENTS), slow,
&fast_double_elements);
BIND(&fast_double_elements);
{
......@@ -644,39 +739,13 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
BIND(&fast);
{
// Disallow pushing onto prototypes. It might be the JSArray prototype.
// Disallow pushing onto non-extensible objects.
Comment("Disallow pushing onto prototypes");
Node* map = LoadMap(receiver);
Node* bit_field2 = LoadMapBitField2(map);
int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) |
(1 << Map::kIsExtensible);
Node* test = Word32And(bit_field2, Int32Constant(mask));
GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)),
&runtime);
// Disallow pushing onto arrays in dictionary named property mode. We need
// to figure out whether the length property is still writable.
Comment("Disallow pushing onto arrays in dictionary named property mode");
GotoIf(IsDictionaryMap(map), &runtime);
// Check whether the length property is writable. The length property is the
// only default named property on arrays. It's nonconfigurable, hence is
// guaranteed to stay the first property.
Node* descriptors = LoadMapDescriptors(map);
Node* details =
LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0));
GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask),
&runtime);
arg_index.Bind(IntPtrConstant(0));
kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
kind = EnsureArrayPushable(receiver, &runtime);
GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS),
&object_push_pre);
Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, context, receiver,
args, arg_index, &smi_transition);
Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, receiver, args,
arg_index, &smi_transition);
args.PopAndReturn(new_length);
}
......@@ -708,22 +777,21 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
BIND(&object_push_pre);
{
Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)),
&double_push, &object_push);
Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push,
&object_push);
}
BIND(&object_push);
{
Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, context, receiver,
args, arg_index, &default_label);
Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, receiver, args,
arg_index, &default_label);
args.PopAndReturn(new_length);
}
BIND(&double_push);
{
Node* new_length =
BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, args,
arg_index, &double_transition);
Node* new_length = BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, receiver, args,
arg_index, &double_transition);
args.PopAndReturn(new_length);
}
......
......@@ -1523,8 +1523,53 @@ Node* CodeStubAssembler::StoreFixedDoubleArrayElement(
return StoreNoWriteBarrier(rep, object, offset, value);
}
Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
Node* array,
Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) {
// Disallow pushing onto prototypes. It might be the JSArray prototype.
// Disallow pushing onto non-extensible objects.
Comment("Disallow pushing onto prototypes");
Node* map = LoadMap(receiver);
Node* bit_field2 = LoadMapBitField2(map);
int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) |
(1 << Map::kIsExtensible);
Node* test = Word32And(bit_field2, Int32Constant(mask));
GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout);
// Disallow pushing onto arrays in dictionary named property mode. We need
// to figure out whether the length property is still writable.
Comment("Disallow pushing onto arrays in dictionary named property mode");
GotoIf(IsDictionaryMap(map), bailout);
// Check whether the length property is writable. The length property is the
// only default named property on arrays. It's nonconfigurable, hence is
// guaranteed to stay the first property.
Node* descriptors = LoadMapDescriptors(map);
Node* details =
LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0));
GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout);
Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
return kind;
}
void CodeStubAssembler::PossiblyGrowElementsCapacity(
ParameterMode mode, ElementsKind kind, Node* array, Node* length,
Variable* var_elements, Node* growth, Label* bailout) {
Label fits(this, var_elements);
Node* capacity =
TaggedToParameter(LoadFixedArrayBaseLength(var_elements->value()), mode);
// length and growth nodes are already in a ParameterMode appropriate
// representation.
Node* new_length = IntPtrOrSmiAdd(growth, length, mode);
GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
var_elements->Bind(GrowElementsCapacity(array, var_elements->value(), kind,
kind, capacity, new_capacity, mode,
bailout));
Goto(&fits);
BIND(&fits);
}
Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array,
CodeStubArguments& args,
Variable& arg_index,
Label* bailout) {
......@@ -1536,46 +1581,22 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
VARIABLE(var_length, OptimalParameterRepresentation(),
TaggedToParameter(LoadJSArrayLength(array), mode));
VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array));
Node* capacity =
TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode);
// Resize the capacity of the fixed array if it doesn't fit.
Label fits(this, &var_elements);
Node* first = arg_index.value();
Node* growth = IntPtrSub(args.GetLength(), first);
Node* new_length =
IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode);
GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind,
kind, capacity, new_capacity, mode,
&pre_bailout));
Goto(&fits);
BIND(&fits);
Node* elements = var_elements.value();
Node* growth = WordToParameter(IntPtrSub(args.GetLength(), first), mode);
PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(),
&var_elements, growth, &pre_bailout);
// Push each argument onto the end of the array now that there is enough
// capacity.
CodeStubAssembler::VariableList push_vars({&var_length}, zone());
Node* elements = var_elements.value();
args.ForEach(
push_vars,
[this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) {
if (IsFastSmiElementsKind(kind)) {
GotoIf(TaggedIsNotSmi(arg), &pre_bailout);
} else if (IsFastDoubleElementsKind(kind)) {
GotoIfNotNumber(arg, &pre_bailout);
}
if (IsFastDoubleElementsKind(kind)) {
Node* double_value = ChangeNumberToFloat64(arg);
StoreFixedDoubleArrayElement(elements, var_length.value(),
Float64SilenceNaN(double_value), mode);
} else {
WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind)
? SKIP_WRITE_BARRIER
: UPDATE_WRITE_BARRIER;
StoreFixedArrayElement(elements, var_length.value(), arg,
barrier_mode, 0, mode);
}
TryStoreArrayElement(kind, mode, &pre_bailout, elements,
var_length.value(), arg);
Increment(var_length, 1, mode);
},
first, nullptr);
......@@ -1600,6 +1621,49 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
return var_tagged_length.value();
}
void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind,
ParameterMode mode, Label* bailout,
Node* elements, Node* index,
Node* value) {
if (IsFastSmiElementsKind(kind)) {
GotoIf(TaggedIsNotSmi(value), bailout);
} else if (IsFastDoubleElementsKind(kind)) {
GotoIfNotNumber(value, bailout);
}
if (IsFastDoubleElementsKind(kind)) {
Node* double_value = ChangeNumberToFloat64(value);
StoreFixedDoubleArrayElement(elements, index,
Float64SilenceNaN(double_value), mode);
} else {
WriteBarrierMode barrier_mode =
IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode);
}
}
void CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array,
Node* value, Label* bailout) {
Comment("BuildAppendJSArray: %s", ElementsKindToString(kind));
ParameterMode mode = OptimalParameterMode();
VARIABLE(var_length, OptimalParameterRepresentation(),
TaggedToParameter(LoadJSArrayLength(array), mode));
VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array));
// Resize the capacity of the fixed array if it doesn't fit.
Node* growth = IntPtrOrSmiConstant(1, mode);
PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(),
&var_elements, growth, bailout);
// Push each argument onto the end of the array now that there is enough
// capacity.
TryStoreArrayElement(kind, mode, bailout, var_elements.value(),
var_length.value(), value);
Increment(var_length, 1, mode);
Node* length = ParameterToTagged(var_length.value(), mode);
StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
}
Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) {
Node* result = Allocate(HeapNumber::kSize, kNone);
Heap::RootListIndex heap_map_index =
......@@ -8485,6 +8549,11 @@ Node* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) {
return Word32Equal(holey_elements, Int32Constant(1));
}
Node* CodeStubAssembler::IsElementsKindGreaterThan(
Node* target_kind, ElementsKind reference_kind) {
return Int32GreaterThan(target_kind, Int32Constant(reference_kind));
}
Node* CodeStubAssembler::IsDebugActive() {
Node* is_debug_active = Load(
MachineType::Uint8(),
......
......@@ -501,9 +501,23 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* object, Node* index, Node* value,
ParameterMode parameter_mode = INTPTR_PARAMETERS);
Node* BuildAppendJSArray(ElementsKind kind, Node* context, Node* array,
// EnsureArrayPushable verifies that receiver is:
// 1. Is not a prototype.
// 2. Is not a dictionary.
// 3. Has a writeable length property.
// It returns ElementsKind as a node for further division into cases.
Node* EnsureArrayPushable(Node* receiver, Label* bailout);
void TryStoreArrayElement(ElementsKind kind, ParameterMode mode,
Label* bailout, Node* elements, Node* index,
Node* value);
// Consumes args into the array, and returns tagged new length.
Node* BuildAppendJSArray(ElementsKind kind, Node* array,
CodeStubArguments& args, Variable& arg_index,
Label* bailout);
// Pushes value onto the end of array.
void BuildAppendJSArray(ElementsKind kind, Node* array, Node* value,
Label* bailout);
void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address,
Node* value);
......@@ -663,6 +677,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* capacity, Node* new_capacity,
ParameterMode mode, Label* bailout);
// Given a need to grow by |growth|, allocate an appropriate new capacity
// if necessary, and return a new elements FixedArray object. Label |bailout|
// is followed for allocation failure.
void PossiblyGrowElementsCapacity(ParameterMode mode, ElementsKind kind,
Node* array, Node* length,
Variable* var_elements, Node* growth,
Label* bailout);
// Allocation site manipulation
void InitializeAllocationMemento(Node* base_allocation,
int base_allocation_size,
......@@ -750,6 +772,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// ElementsKind helpers:
Node* IsFastElementsKind(Node* elements_kind);
Node* IsHoleyFastElementsKind(Node* elements_kind);
Node* IsElementsKindGreaterThan(Node* target_kind,
ElementsKind reference_kind);
// String helpers.
// Load a character from a String (might flatten a ConsString).
......
......@@ -1000,57 +1000,6 @@ function ArraySort(comparefn) {
return InnerArraySort(array, length, comparefn);
}
// The following functions cannot be made efficient on sparse arrays while
// preserving the semantics, since the calls to the receiver function can add
// or delete elements from the array.
function InnerArrayFilter(f, receiver, array, length, result) {
var result_length = 0;
for (var i = 0; i < length; i++) {
if (i in array) {
var element = array[i];
if (%_Call(f, receiver, element, i, array)) {
%CreateDataProperty(result, result_length, element);
result_length++;
}
}
}
return result;
}
function ArrayFilter(f, receiver) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.filter");
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f);
var result = ArraySpeciesCreate(array, 0);
return InnerArrayFilter(f, receiver, array, length, result);
}
function ArrayMap(f, receiver) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.map");
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f);
var result = ArraySpeciesCreate(array, length);
for (var i = 0; i < length; i++) {
if (i in array) {
var element = array[i];
%CreateDataProperty(result, i, %_Call(f, receiver, element, i, array));
}
}
return result;
}
function ArrayLastIndexOf(element, index) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf");
......@@ -1381,8 +1330,6 @@ utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"slice", getFunction("slice", ArraySlice, 2),
"splice", getFunction("splice", ArraySplice, 2),
"sort", getFunction("sort", ArraySort),
"filter", getFunction("filter", ArrayFilter, 1),
"map", getFunction("map", ArrayMap, 1),
"indexOf", getFunction("indexOf", null, 1),
"lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
"copyWithin", getFunction("copyWithin", ArrayCopyWithin, 2),
......@@ -1439,7 +1386,6 @@ utils.Export(function(to) {
to.ArrayPush = ArrayPush;
to.ArrayToString = ArrayToString;
to.ArrayValues = IteratorFunctions.values,
to.InnerArrayFilter = InnerArrayFilter;
to.InnerArrayFind = InnerArrayFind;
to.InnerArrayFindIndex = InnerArrayFindIndex;
to.InnerArrayJoin = InnerArrayJoin;
......
......@@ -20,7 +20,6 @@ var GlobalArray = global.Array;
var GlobalArrayBuffer = global.ArrayBuffer;
var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
var GlobalObject = global.Object;
var InnerArrayFilter;
var InnerArrayFind;
var InnerArrayFindIndex;
var InnerArrayJoin;
......@@ -57,7 +56,6 @@ utils.Import(function(from) {
ArrayValues = from.ArrayValues;
GetIterator = from.GetIterator;
GetMethod = from.GetMethod;
InnerArrayFilter = from.InnerArrayFilter;
InnerArrayFind = from.InnerArrayFind;
InnerArrayFindIndex = from.InnerArrayFindIndex;
InnerArrayJoin = from.InnerArrayJoin;
......@@ -415,6 +413,23 @@ function TypedArrayForEach(f, receiver) {
}
%FunctionSetLength(TypedArrayForEach, 1);
// The following functions cannot be made efficient on sparse arrays while
// preserving the semantics, since the calls to the receiver function can add
// or delete elements from the array.
function InnerTypedArrayFilter(f, receiver, array, length, result) {
var result_length = 0;
for (var i = 0; i < length; i++) {
if (i in array) {
var element = array[i];
if (%_Call(f, receiver, element, i, array)) {
%CreateDataProperty(result, result_length, element);
result_length++;
}
}
}
return result;
}
// ES6 draft 07-15-13, section 22.2.3.9
function TypedArrayFilter(f, thisArg) {
......@@ -423,7 +438,7 @@ function TypedArrayFilter(f, thisArg) {
var length = %_TypedArrayGetLength(this);
if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f);
var result = new InternalArray();
InnerArrayFilter(f, thisArg, this, length, result);
InnerTypedArrayFilter(f, thisArg, this, length, result);
var captured = result.length;
var output = TypedArraySpeciesCreate(this, captured);
for (var i = 0; i < captured; i++) {
......
......@@ -1807,9 +1807,8 @@ class AppendJSArrayCodeStubAssembler : public CodeStubAssembler {
Variable arg_index(this, MachineType::PointerRepresentation());
Label bailout(this);
arg_index.Bind(IntPtrConstant(0));
Node* length = BuildAppendJSArray(
kind_, HeapConstant(Handle<HeapObject>(isolate->context(), isolate)),
HeapConstant(array), args, arg_index, &bailout);
Node* length = BuildAppendJSArray(kind_, HeapConstant(array), args,
arg_index, &bailout);
Return(length);
Bind(&bailout);
......
......@@ -264,7 +264,7 @@ function testOmittedBuiltin(throwing, omitted) {
}
testTrace("testArrayNative", testArrayNative, ["Array.map (native)"]);
testTrace("testArrayNative", testArrayNative, ["Array.map"]);
testTrace("testNested", testNested, ["at one", "at two", "at three"]);
testTrace("testMethodNameInference", testMethodNameInference, ["at Foo.bar"]);
testTrace("testImplicitConversion", testImplicitConversion, ["at Nirk.valueOf"]);
......
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