Commit 11d80c95 authored by jgruber's avatar jgruber Committed by Commit bot

[array] Fast allocation in Array.p.map and Array.p.filter

No need to call through ConstructJS -> ArrayCode -> ArrayConstructorStub
-> AllocateJSArray if we can call AllocateJSArray directly.

This also moves ArraySpeciesCreate to builtins-array-gen to free
up space in the binary.

BUG=v8:6354

Review-Url: https://codereview.chromium.org/2874833004
Cr-Commit-Position: refs/heads/master@{#45276}
parent 0e788e32
......@@ -91,7 +91,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
void FilterResultGenerator() {
// 7. Let A be ArraySpeciesCreate(O, 0).
a_.Bind(ArraySpeciesCreate(context(), o(), SmiConstant(0)));
Node* len = SmiConstant(0);
ArraySpeciesCreate(len);
}
Node* FilterProcessor(Node* k_value, Node* k) {
......@@ -160,37 +161,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
return a();
}
void MapResultGenerator() {
Label runtime(this), done(this, {&a_});
GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &runtime);
Node* o_map = LoadMap(o());
Node* const initial_array_prototype = LoadContextElement(
LoadNativeContext(context()), Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
Node* proto = LoadMapPrototype(o_map);
GotoIf(WordNotEqual(proto, initial_array_prototype), &runtime);
Node* species_protector = SpeciesProtectorConstant();
Node* value = LoadObjectField(species_protector, Cell::kValueOffset);
Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
GotoIf(WordEqual(value, protector_invalid), &runtime);
Node* const initial_array_constructor = LoadContextElement(
LoadNativeContext(context()), Context::ARRAY_FUNCTION_INDEX);
a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
initial_array_constructor, len_));
Goto(&done);
BIND(&runtime);
{
// 5. Let A be ? ArraySpeciesCreate(O, len).
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
constructor, len_));
Goto(&fully_spec_compliant_);
}
BIND(&done);
}
void MapResultGenerator() { ArraySpeciesCreate(len_); }
Node* SpecCompliantMapProcessor(Node* k_value, Node* k) {
// i. Let kValue be ? Get(O, Pk). Performed by the caller of
......@@ -716,6 +687,51 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
}
}
// Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
void ArraySpeciesCreate(Node* len) {
Label runtime(this, Label::kDeferred), done(this);
Node* const original_map = LoadMap(o());
GotoIf(Word32NotEqual(LoadMapInstanceType(original_map),
Int32Constant(JS_ARRAY_TYPE)),
&runtime);
Node* const native_context = LoadNativeContext(context());
Node* const initial_array_prototype = LoadContextElement(
native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
Node* proto = LoadMapPrototype(original_map);
GotoIf(WordNotEqual(proto, initial_array_prototype), &runtime);
Node* species_protector = SpeciesProtectorConstant();
Node* value = LoadObjectField(species_protector, Cell::kValueOffset);
Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
GotoIf(WordEqual(value, protector_invalid), &runtime);
GotoIfNot(TaggedIsPositiveSmi(len), &runtime);
GotoIf(SmiAbove(len, SmiConstant(JSArray::kInitialMaxFastElementArray)),
&runtime);
const ElementsKind elements_kind =
GetHoleyElementsKind(GetInitialFastElementsKind());
Node* array_map = LoadJSArrayElementsMap(elements_kind, native_context);
a_.Bind(AllocateJSArray(FAST_SMI_ELEMENTS, array_map, len, len, nullptr,
CodeStubAssembler::SMI_PARAMETERS));
Goto(&done);
BIND(&runtime);
{
// 5. Let A be ? ArraySpeciesCreate(O, len).
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
constructor, len));
Goto(&fully_spec_compliant_);
}
BIND(&done);
}
Node* callbackfn_ = nullptr;
Node* o_ = nullptr;
Node* this_arg_ = nullptr;
......
......@@ -8859,16 +8859,6 @@ Node* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map,
return iterator;
}
Node* CodeStubAssembler::ArraySpeciesCreate(Node* context, Node* originalArray,
Node* len) {
// TODO(mvstanton): Install a fast path as well, which avoids the runtime
// call.
Node* constructor =
CallRuntime(Runtime::kArraySpeciesConstructor, context, originalArray);
return ConstructJS(CodeFactory::Construct(isolate()), context, constructor,
len);
}
Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE));
......
......@@ -621,9 +621,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* AllocateJSArrayIterator(Node* array, Node* array_map, Node* map);
// Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
Node* ArraySpeciesCreate(Node* context, Node* originalArray, Node* len);
void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index,
Node* to_index,
Heap::RootListIndex value_root_index,
......
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