Commit 04746c81 authored by peterwmwong's avatar peterwmwong Committed by Commit Bot

[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: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49706}
parent 32033f4f
......@@ -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/);
......
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