[builtin] Fast paths for Array.concat
- Initial implementation of Array.concat on Torque. - Adds fast paths for `[].concat()` and `x.concat()`, these are now as fast as `[...x]` and `x.slice()` for non-optimised code. Bug: v8:7152 Change-Id: I86ca15e4e1e67f53424ef0c8bb7eea12d7e660b3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3026716 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/master@{#75737}
This commit is contained in:
parent
5a4f8a08e8
commit
6ca1f677de
@ -610,6 +610,7 @@ filegroup(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"src/builtins/aggregate-error.tq",
|
"src/builtins/aggregate-error.tq",
|
||||||
"src/builtins/array-at.tq",
|
"src/builtins/array-at.tq",
|
||||||
|
"src/builtins/array-concat.tq",
|
||||||
"src/builtins/array-copywithin.tq",
|
"src/builtins/array-copywithin.tq",
|
||||||
"src/builtins/array-every.tq",
|
"src/builtins/array-every.tq",
|
||||||
"src/builtins/array-filter.tq",
|
"src/builtins/array-filter.tq",
|
||||||
|
1
BUILD.gn
1
BUILD.gn
@ -1396,6 +1396,7 @@ action("postmortem-metadata") {
|
|||||||
torque_files = [
|
torque_files = [
|
||||||
"src/builtins/aggregate-error.tq",
|
"src/builtins/aggregate-error.tq",
|
||||||
"src/builtins/array-at.tq",
|
"src/builtins/array-at.tq",
|
||||||
|
"src/builtins/array-concat.tq",
|
||||||
"src/builtins/array-copywithin.tq",
|
"src/builtins/array-copywithin.tq",
|
||||||
"src/builtins/array-every.tq",
|
"src/builtins/array-every.tq",
|
||||||
"src/builtins/array-filter.tq",
|
"src/builtins/array-filter.tq",
|
||||||
|
49
src/builtins/array-concat.tq
Normal file
49
src/builtins/array-concat.tq
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
namespace array {
|
||||||
|
|
||||||
|
extern builtin ArrayConcat(Context, JSFunction, JSAny, int32): JSAny;
|
||||||
|
|
||||||
|
transitioning javascript builtin
|
||||||
|
ArrayPrototypeConcat(
|
||||||
|
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
|
||||||
|
// Fast path if we invoke as `x.concat()`.
|
||||||
|
if (arguments.length == 0) {
|
||||||
|
typeswitch (receiver) {
|
||||||
|
case (a: FastJSArrayForCopy): {
|
||||||
|
return CloneFastJSArray(context, a);
|
||||||
|
}
|
||||||
|
case (JSAny): {
|
||||||
|
// Fallthrough.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fast path if we invoke as `[].concat(x)`.
|
||||||
|
try {
|
||||||
|
const receiverAsArray: FastJSArrayForConcat =
|
||||||
|
Cast<FastJSArrayForConcat>(receiver)
|
||||||
|
otherwise ReceiverIsNotFastJSArrayForConcat;
|
||||||
|
if (receiverAsArray.IsEmpty() && arguments.length == 1) {
|
||||||
|
typeswitch (arguments[0]) {
|
||||||
|
case (a: FastJSArrayForCopy): {
|
||||||
|
return CloneFastJSArray(context, a);
|
||||||
|
}
|
||||||
|
case (JSAny): {
|
||||||
|
// Fallthrough.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} label ReceiverIsNotFastJSArrayForConcat {
|
||||||
|
// Fallthrough.
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(victorgomes): Implement slow path ArrayConcat in Torque.
|
||||||
|
tail ArrayConcat(
|
||||||
|
context, LoadTargetFromFrame(), Undefined,
|
||||||
|
Convert<int32>(arguments.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace array
|
@ -1198,6 +1198,7 @@ extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
|
|||||||
extern macro IsNoElementsProtectorCellInvalid(): bool;
|
extern macro IsNoElementsProtectorCellInvalid(): bool;
|
||||||
extern macro IsArrayIteratorProtectorCellInvalid(): bool;
|
extern macro IsArrayIteratorProtectorCellInvalid(): bool;
|
||||||
extern macro IsArraySpeciesProtectorCellInvalid(): bool;
|
extern macro IsArraySpeciesProtectorCellInvalid(): bool;
|
||||||
|
extern macro IsIsConcatSpreadableProtectorCellInvalid(): bool;
|
||||||
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
|
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
|
||||||
extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
|
extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
|
||||||
extern macro IsMockArrayBufferAllocatorFlag(): bool;
|
extern macro IsMockArrayBufferAllocatorFlag(): bool;
|
||||||
|
@ -551,6 +551,15 @@ Cast<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject):
|
|||||||
return %RawDownCast<FastJSArrayForCopy>(a);
|
return %RawDownCast<FastJSArrayForCopy>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cast<FastJSArrayForConcat>(implicit context: Context)(o: HeapObject):
|
||||||
|
FastJSArrayForConcat
|
||||||
|
labels CastError {
|
||||||
|
if (IsArraySpeciesProtectorCellInvalid()) goto CastError;
|
||||||
|
if (IsIsConcatSpreadableProtectorCellInvalid()) goto CastError;
|
||||||
|
const a = Cast<FastJSArrayForRead>(o) otherwise CastError;
|
||||||
|
return %RawDownCast<FastJSArrayForConcat>(a);
|
||||||
|
}
|
||||||
|
|
||||||
Cast<FastJSArrayWithNoCustomIteration>(implicit context: Context)(
|
Cast<FastJSArrayWithNoCustomIteration>(implicit context: Context)(
|
||||||
o: HeapObject): FastJSArrayWithNoCustomIteration
|
o: HeapObject): FastJSArrayWithNoCustomIteration
|
||||||
labels CastError {
|
labels CastError {
|
||||||
|
@ -6195,6 +6195,13 @@ TNode<BoolT> CodeStubAssembler::IsArraySpeciesProtectorCellInvalid() {
|
|||||||
return TaggedEqual(cell_value, invalid);
|
return TaggedEqual(cell_value, invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TNode<BoolT> CodeStubAssembler::IsIsConcatSpreadableProtectorCellInvalid() {
|
||||||
|
TNode<Smi> invalid = SmiConstant(Protectors::kProtectorInvalid);
|
||||||
|
TNode<PropertyCell> cell = IsConcatSpreadableProtectorConstant();
|
||||||
|
TNode<Object> cell_value = LoadObjectField(cell, PropertyCell::kValueOffset);
|
||||||
|
return TaggedEqual(cell_value, invalid);
|
||||||
|
}
|
||||||
|
|
||||||
TNode<BoolT> CodeStubAssembler::IsTypedArraySpeciesProtectorCellInvalid() {
|
TNode<BoolT> CodeStubAssembler::IsTypedArraySpeciesProtectorCellInvalid() {
|
||||||
TNode<Smi> invalid = SmiConstant(Protectors::kProtectorInvalid);
|
TNode<Smi> invalid = SmiConstant(Protectors::kProtectorInvalid);
|
||||||
TNode<PropertyCell> cell = TypedArraySpeciesProtectorConstant();
|
TNode<PropertyCell> cell = TypedArraySpeciesProtectorConstant();
|
||||||
|
@ -68,6 +68,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
|||||||
AsyncGeneratorYieldResolveSharedFun) \
|
AsyncGeneratorYieldResolveSharedFun) \
|
||||||
V(AsyncIteratorValueUnwrapSharedFun, async_iterator_value_unwrap_shared_fun, \
|
V(AsyncIteratorValueUnwrapSharedFun, async_iterator_value_unwrap_shared_fun, \
|
||||||
AsyncIteratorValueUnwrapSharedFun) \
|
AsyncIteratorValueUnwrapSharedFun) \
|
||||||
|
V(IsConcatSpreadableProtector, is_concat_spreadable_protector, \
|
||||||
|
IsConcatSpreadableProtector) \
|
||||||
V(MapIteratorProtector, map_iterator_protector, MapIteratorProtector) \
|
V(MapIteratorProtector, map_iterator_protector, MapIteratorProtector) \
|
||||||
V(NoElementsProtector, no_elements_protector, NoElementsProtector) \
|
V(NoElementsProtector, no_elements_protector, NoElementsProtector) \
|
||||||
V(MegaDOMProtector, mega_dom_protector, MegaDOMProtector) \
|
V(MegaDOMProtector, mega_dom_protector, MegaDOMProtector) \
|
||||||
@ -2546,6 +2548,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
|||||||
TNode<BoolT> IsPromiseResolveProtectorCellInvalid();
|
TNode<BoolT> IsPromiseResolveProtectorCellInvalid();
|
||||||
TNode<BoolT> IsPromiseThenProtectorCellInvalid();
|
TNode<BoolT> IsPromiseThenProtectorCellInvalid();
|
||||||
TNode<BoolT> IsArraySpeciesProtectorCellInvalid();
|
TNode<BoolT> IsArraySpeciesProtectorCellInvalid();
|
||||||
|
TNode<BoolT> IsIsConcatSpreadableProtectorCellInvalid();
|
||||||
TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid();
|
TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid();
|
||||||
TNode<BoolT> IsRegExpSpeciesProtectorCellInvalid();
|
TNode<BoolT> IsRegExpSpeciesProtectorCellInvalid();
|
||||||
TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid();
|
TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid();
|
||||||
|
@ -560,6 +560,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtin id) {
|
|||||||
case Builtin::kArrayPrototypeValues:
|
case Builtin::kArrayPrototypeValues:
|
||||||
case Builtin::kArrayIncludes:
|
case Builtin::kArrayIncludes:
|
||||||
case Builtin::kArrayPrototypeAt:
|
case Builtin::kArrayPrototypeAt:
|
||||||
|
case Builtin::kArrayPrototypeConcat:
|
||||||
case Builtin::kArrayPrototypeEntries:
|
case Builtin::kArrayPrototypeEntries:
|
||||||
case Builtin::kArrayPrototypeFill:
|
case Builtin::kArrayPrototypeFill:
|
||||||
case Builtin::kArrayPrototypeFind:
|
case Builtin::kArrayPrototypeFind:
|
||||||
|
@ -1741,8 +1741,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
|||||||
JSObject::AddProperty(isolate_, proto, factory->constructor_string(),
|
JSObject::AddProperty(isolate_, proto, factory->constructor_string(),
|
||||||
array_function, DONT_ENUM);
|
array_function, DONT_ENUM);
|
||||||
|
|
||||||
SimpleInstallFunction(isolate_, proto, "concat", Builtin::kArrayConcat, 1,
|
SimpleInstallFunction(isolate_, proto, "concat",
|
||||||
false);
|
Builtin::kArrayPrototypeConcat, 1, false);
|
||||||
SimpleInstallFunction(isolate_, proto, "copyWithin",
|
SimpleInstallFunction(isolate_, proto, "copyWithin",
|
||||||
Builtin::kArrayPrototypeCopyWithin, 2, false);
|
Builtin::kArrayPrototypeCopyWithin, 2, false);
|
||||||
SimpleInstallFunction(isolate_, proto, "fill", Builtin::kArrayPrototypeFill,
|
SimpleInstallFunction(isolate_, proto, "fill", Builtin::kArrayPrototypeFill,
|
||||||
|
@ -66,6 +66,10 @@ transient type FastJSArrayForRead extends JSArray;
|
|||||||
// A FastJSArray when the global ArraySpeciesProtector is not invalidated.
|
// A FastJSArray when the global ArraySpeciesProtector is not invalidated.
|
||||||
transient type FastJSArrayForCopy extends FastJSArray;
|
transient type FastJSArrayForCopy extends FastJSArray;
|
||||||
|
|
||||||
|
// A FastJSArray when the global ArraySpeciesProtector and
|
||||||
|
// IsConcatSpreadableProtector are not invalidated.
|
||||||
|
transient type FastJSArrayForConcat extends FastJSArrayForRead;
|
||||||
|
|
||||||
// A FastJSArray when the global ArrayIteratorProtector is not invalidated.
|
// A FastJSArray when the global ArrayIteratorProtector is not invalidated.
|
||||||
transient type FastJSArrayWithNoCustomIteration extends FastJSArray;
|
transient type FastJSArrayWithNoCustomIteration extends FastJSArray;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user