[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 = [
|
||||
"src/builtins/aggregate-error.tq",
|
||||
"src/builtins/array-at.tq",
|
||||
"src/builtins/array-concat.tq",
|
||||
"src/builtins/array-copywithin.tq",
|
||||
"src/builtins/array-every.tq",
|
||||
"src/builtins/array-filter.tq",
|
||||
|
1
BUILD.gn
1
BUILD.gn
@ -1396,6 +1396,7 @@ action("postmortem-metadata") {
|
||||
torque_files = [
|
||||
"src/builtins/aggregate-error.tq",
|
||||
"src/builtins/array-at.tq",
|
||||
"src/builtins/array-concat.tq",
|
||||
"src/builtins/array-copywithin.tq",
|
||||
"src/builtins/array-every.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 IsArrayIteratorProtectorCellInvalid(): bool;
|
||||
extern macro IsArraySpeciesProtectorCellInvalid(): bool;
|
||||
extern macro IsIsConcatSpreadableProtectorCellInvalid(): bool;
|
||||
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bool;
|
||||
extern macro IsPromiseSpeciesProtectorCellInvalid(): bool;
|
||||
extern macro IsMockArrayBufferAllocatorFlag(): bool;
|
||||
|
@ -551,6 +551,15 @@ Cast<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject):
|
||||
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)(
|
||||
o: HeapObject): FastJSArrayWithNoCustomIteration
|
||||
labels CastError {
|
||||
|
@ -6195,6 +6195,13 @@ TNode<BoolT> CodeStubAssembler::IsArraySpeciesProtectorCellInvalid() {
|
||||
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<Smi> invalid = SmiConstant(Protectors::kProtectorInvalid);
|
||||
TNode<PropertyCell> cell = TypedArraySpeciesProtectorConstant();
|
||||
|
@ -68,6 +68,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
AsyncGeneratorYieldResolveSharedFun) \
|
||||
V(AsyncIteratorValueUnwrapSharedFun, async_iterator_value_unwrap_shared_fun, \
|
||||
AsyncIteratorValueUnwrapSharedFun) \
|
||||
V(IsConcatSpreadableProtector, is_concat_spreadable_protector, \
|
||||
IsConcatSpreadableProtector) \
|
||||
V(MapIteratorProtector, map_iterator_protector, MapIteratorProtector) \
|
||||
V(NoElementsProtector, no_elements_protector, NoElementsProtector) \
|
||||
V(MegaDOMProtector, mega_dom_protector, MegaDOMProtector) \
|
||||
@ -2546,6 +2548,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<BoolT> IsPromiseResolveProtectorCellInvalid();
|
||||
TNode<BoolT> IsPromiseThenProtectorCellInvalid();
|
||||
TNode<BoolT> IsArraySpeciesProtectorCellInvalid();
|
||||
TNode<BoolT> IsIsConcatSpreadableProtectorCellInvalid();
|
||||
TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid();
|
||||
TNode<BoolT> IsRegExpSpeciesProtectorCellInvalid();
|
||||
TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid();
|
||||
|
@ -560,6 +560,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtin id) {
|
||||
case Builtin::kArrayPrototypeValues:
|
||||
case Builtin::kArrayIncludes:
|
||||
case Builtin::kArrayPrototypeAt:
|
||||
case Builtin::kArrayPrototypeConcat:
|
||||
case Builtin::kArrayPrototypeEntries:
|
||||
case Builtin::kArrayPrototypeFill:
|
||||
case Builtin::kArrayPrototypeFind:
|
||||
|
@ -1741,8 +1741,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
JSObject::AddProperty(isolate_, proto, factory->constructor_string(),
|
||||
array_function, DONT_ENUM);
|
||||
|
||||
SimpleInstallFunction(isolate_, proto, "concat", Builtin::kArrayConcat, 1,
|
||||
false);
|
||||
SimpleInstallFunction(isolate_, proto, "concat",
|
||||
Builtin::kArrayPrototypeConcat, 1, false);
|
||||
SimpleInstallFunction(isolate_, proto, "copyWithin",
|
||||
Builtin::kArrayPrototypeCopyWithin, 2, false);
|
||||
SimpleInstallFunction(isolate_, proto, "fill", Builtin::kArrayPrototypeFill,
|
||||
|
@ -66,6 +66,10 @@ transient type FastJSArrayForRead extends JSArray;
|
||||
// A FastJSArray when the global ArraySpeciesProtector is not invalidated.
|
||||
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.
|
||||
transient type FastJSArrayWithNoCustomIteration extends FastJSArray;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user