[typedarray] Port TA.p.find() to CSA TFJ
This reduces the overhead of calling the builtin. Quick measurements show >5x improvement. As the typed array's size grows, iterating dominates and the performance gap closes. https://github.com/peterwmwong/v8-perf/blob/master/typedarray-find/README.md Bug: v8:5929 Change-Id: Ia74546bb46d446c6161c8956e350d4b5cdc1b328 Reviewed-on: https://chromium-review.googlesource.com/792454 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#49706}
This commit is contained in:
parent
32033f4f4f
commit
04746c8109
@ -3031,6 +3031,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
Builtins::kTypedArrayPrototypeEvery, 1, false);
|
||||
SimpleInstallFunction(prototype, "fill",
|
||||
Builtins::kTypedArrayPrototypeFill, 1, false);
|
||||
SimpleInstallFunction(prototype, "find", Builtins::kTypedArrayPrototypeFind,
|
||||
1, false);
|
||||
SimpleInstallFunction(prototype, "forEach",
|
||||
Builtins::kTypedArrayPrototypeForEach, 1, false);
|
||||
SimpleInstallFunction(prototype, "includes",
|
||||
|
@ -31,6 +31,19 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
||||
typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
|
||||
PostLoopAction;
|
||||
|
||||
void FindResultGenerator() { a_.Bind(UndefinedConstant()); }
|
||||
|
||||
Node* FindProcessor(Node* k_value, Node* k) {
|
||||
Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
|
||||
this_arg(), k_value, k, o());
|
||||
Label false_continue(this), return_true(this);
|
||||
BranchIfToBooleanIsTrue(value, &return_true, &false_continue);
|
||||
BIND(&return_true);
|
||||
ReturnFromBuiltin(k_value);
|
||||
BIND(&false_continue);
|
||||
return a();
|
||||
}
|
||||
|
||||
void ForEachResultGenerator() { a_.Bind(UndefinedConstant()); }
|
||||
|
||||
Node* ForEachProcessor(Node* k_value, Node* k) {
|
||||
@ -1593,6 +1606,27 @@ TF_BUILTIN(CloneFastJSArray, ArrayBuiltinCodeStubAssembler) {
|
||||
Return(CloneFastJSArray(context, array, mode));
|
||||
}
|
||||
|
||||
// ES #sec-get-%typedarray%.prototype.find
|
||||
TF_BUILTIN(TypedArrayPrototypeFind, ArrayBuiltinCodeStubAssembler) {
|
||||
Node* argc =
|
||||
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
|
||||
CodeStubArguments args(this, argc);
|
||||
Node* context = Parameter(BuiltinDescriptor::kContext);
|
||||
Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
|
||||
Node* receiver = args.GetReceiver();
|
||||
Node* callbackfn = args.GetOptionalArgumentValue(0);
|
||||
Node* this_arg = args.GetOptionalArgumentValue(1);
|
||||
|
||||
InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
|
||||
new_target, argc);
|
||||
|
||||
GenerateIteratingTypedArrayBuiltinBody(
|
||||
"%TypedArray%.prototype.find",
|
||||
&ArrayBuiltinCodeStubAssembler::FindResultGenerator,
|
||||
&ArrayBuiltinCodeStubAssembler::FindProcessor,
|
||||
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
|
||||
}
|
||||
|
||||
TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
|
||||
Node* context = Parameter(Descriptor::kContext);
|
||||
Node* receiver = Parameter(Descriptor::kReceiver);
|
||||
|
@ -1046,6 +1046,9 @@ namespace internal {
|
||||
CPP(TypedArrayPrototypeCopyWithin) \
|
||||
/* ES6 #sec-%typedarray%.prototype.fill */ \
|
||||
CPP(TypedArrayPrototypeFill) \
|
||||
/* ES6 %TypedArray%.prototype.find */ \
|
||||
TFJ(TypedArrayPrototypeFind, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES7 #sec-%typedarray%.prototype.includes */ \
|
||||
CPP(TypedArrayPrototypeIncludes) \
|
||||
/* ES6 #sec-%typedarray%.prototype.indexof */ \
|
||||
|
@ -1354,7 +1354,6 @@ utils.Export(function(to) {
|
||||
to.ArrayPush = ArrayPush;
|
||||
to.ArrayToString = ArrayToString;
|
||||
to.ArrayValues = ArrayValues;
|
||||
to.InnerArrayFind = InnerArrayFind;
|
||||
to.InnerArrayFindIndex = InnerArrayFindIndex;
|
||||
to.InnerArrayJoin = InnerArrayJoin;
|
||||
to.InnerArraySort = InnerArraySort;
|
||||
|
@ -19,7 +19,6 @@ var GlobalArray = global.Array;
|
||||
var GlobalArrayBuffer = global.ArrayBuffer;
|
||||
var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
|
||||
var GlobalObject = global.Object;
|
||||
var InnerArrayFind;
|
||||
var InnerArrayFindIndex;
|
||||
var InnerArrayJoin;
|
||||
var InnerArraySort;
|
||||
@ -66,7 +65,6 @@ var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
|
||||
utils.Import(function(from) {
|
||||
GetIterator = from.GetIterator;
|
||||
GetMethod = from.GetMethod;
|
||||
InnerArrayFind = from.InnerArrayFind;
|
||||
InnerArrayFindIndex = from.InnerArrayFindIndex;
|
||||
InnerArrayJoin = from.InnerArrayJoin;
|
||||
InnerArraySort = from.InnerArraySort;
|
||||
@ -297,21 +295,6 @@ DEFINE_METHOD_LEN(
|
||||
1 /* Set function length. */
|
||||
);
|
||||
|
||||
|
||||
// ES6 draft 07-15-13, section 22.2.3.10
|
||||
DEFINE_METHOD_LEN(
|
||||
GlobalTypedArray.prototype,
|
||||
find(predicate, thisArg) {
|
||||
ValidateTypedArray(this, "%TypedArray%.prototype.find");
|
||||
|
||||
var length = %_TypedArrayGetLength(this);
|
||||
|
||||
return InnerArrayFind(predicate, thisArg, this, length);
|
||||
},
|
||||
1 /* Set function length. */
|
||||
);
|
||||
|
||||
|
||||
// ES6 draft 07-15-13, section 22.2.3.11
|
||||
DEFINE_METHOD_LEN(
|
||||
GlobalTypedArray.prototype,
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --stack-size=100 --harmony
|
||||
// Flags: --allow-natives-syntax --stack-size=100 --harmony
|
||||
|
||||
function test(f, expected, type) {
|
||||
try {
|
||||
@ -15,6 +15,18 @@ function test(f, expected, type) {
|
||||
assertUnreachable("Exception expected");
|
||||
}
|
||||
|
||||
const typedArrayConstructors = [
|
||||
Uint8Array,
|
||||
Int8Array,
|
||||
Uint16Array,
|
||||
Int16Array,
|
||||
Uint32Array,
|
||||
Int32Array,
|
||||
Float32Array,
|
||||
Float64Array,
|
||||
Uint8ClampedArray
|
||||
];
|
||||
|
||||
// === Error ===
|
||||
|
||||
// kCyclicProto
|
||||
@ -156,6 +168,15 @@ test(function() {
|
||||
Object.defineProperty(o, "x", { value: 1 });
|
||||
}, "Cannot define property x, object is not extensible", TypeError);
|
||||
|
||||
// kDetachedOperation
|
||||
for (constructor of typedArrayConstructors) {
|
||||
test(() => {
|
||||
const ta = new constructor([1]);
|
||||
%ArrayBufferNeuter(ta.buffer);
|
||||
ta.find(() => {});
|
||||
}, "Cannot perform %TypedArray%.prototype.find on a detached ArrayBuffer", TypeError);
|
||||
}
|
||||
|
||||
// kFirstArgumentNotRegExp
|
||||
test(function() {
|
||||
"a".startsWith(/a/);
|
||||
|
Loading…
Reference in New Issue
Block a user