[builtins] FastCreateDataProperty avoids runtime calls
If we make use of this in the generic Array.prototype.filter case we get a performance boost of over 60%. Bug: v8:8213, chromium:920187 Change-Id: Ia116a852f355a9f037850aee86db7284f0023929 Reviewed-on: https://chromium-review.googlesource.com/c/1484297 Reviewed-by: Daniel Clifford <danno@chromium.org> Commit-Queue: Michael Stanton <mvstanton@chromium.org> Cr-Commit-Position: refs/heads/master@{#59979}
This commit is contained in:
parent
a66712deba
commit
7d971fb022
@ -46,7 +46,7 @@ namespace array_filter {
|
||||
// the output array. After incrementing k and to, we can glide into the loop
|
||||
// continuation builtin.
|
||||
if (ToBoolean(result)) {
|
||||
CreateDataProperty(outputArray, numberTo, valueK);
|
||||
FastCreateDataProperty(outputArray, numberTo, valueK);
|
||||
numberTo = numberTo + 1;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ namespace array_filter {
|
||||
// iii. If selected is true, then...
|
||||
if (ToBoolean(result)) {
|
||||
// 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
|
||||
CreateDataProperty(array, to, kValue);
|
||||
FastCreateDataProperty(array, to, kValue);
|
||||
// 2. Increase to by 1.
|
||||
to = to + 1;
|
||||
}
|
||||
@ -123,7 +123,7 @@ namespace array_filter {
|
||||
fastOutputW.Push(value) otherwise SlowStore;
|
||||
}
|
||||
label SlowStore {
|
||||
CreateDataProperty(fastOutputW.stable, to, value);
|
||||
FastCreateDataProperty(fastOutputW.stable, to, value);
|
||||
}
|
||||
to = to + 1;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace array_map {
|
||||
// continuation builtin.
|
||||
|
||||
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
|
||||
CreateDataProperty(outputArray, numberK, result);
|
||||
FastCreateDataProperty(outputArray, numberK, result);
|
||||
|
||||
// 7d. Increase k by 1.
|
||||
numberK = numberK + 1;
|
||||
@ -78,7 +78,7 @@ namespace array_map {
|
||||
Call(context, callbackfn, thisArg, kValue, k, o);
|
||||
|
||||
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
|
||||
CreateDataProperty(array, k, mappedValue);
|
||||
FastCreateDataProperty(array, k, mappedValue);
|
||||
}
|
||||
|
||||
// 7d. Increase k by 1. (done by the loop).
|
||||
|
@ -39,7 +39,7 @@ namespace array_of {
|
||||
|
||||
// b. Let Pk be ! ToString(k).
|
||||
// c. Perform ? CreateDataPropertyOrThrow(A, Pk, kValue).
|
||||
CreateDataProperty(a, k, kValue);
|
||||
FastCreateDataProperty(a, k, kValue);
|
||||
|
||||
// d. Increase k by 1.
|
||||
k++;
|
||||
|
@ -193,7 +193,7 @@ namespace array_slice {
|
||||
const kValue: Object = GetProperty(o, pK);
|
||||
|
||||
// ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(n), kValue).
|
||||
CreateDataProperty(a, n, kValue);
|
||||
FastCreateDataProperty(a, n, kValue);
|
||||
}
|
||||
|
||||
// d. Increase k by 1.
|
||||
|
@ -197,7 +197,7 @@ namespace array_splice {
|
||||
const fromValue: Object = GetProperty(o, from);
|
||||
|
||||
// ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue).
|
||||
CreateDataProperty(a, k, fromValue);
|
||||
FastCreateDataProperty(a, k, fromValue);
|
||||
}
|
||||
|
||||
// d. Increment k by 1.
|
||||
|
@ -675,8 +675,6 @@ extern builtin ToString(Context, Object): String;
|
||||
extern transitioning runtime NormalizeElements(Context, JSObject);
|
||||
extern transitioning runtime TransitionElementsKindWithKind(
|
||||
Context, JSObject, Smi);
|
||||
extern transitioning runtime CreateDataProperty(implicit context: Context)(
|
||||
JSReceiver, Object, Object);
|
||||
|
||||
extern macro LoadBufferObject(RawPtr, constexpr int32): Object;
|
||||
extern macro LoadBufferPointer(RawPtr, constexpr int32): RawPtr;
|
||||
@ -1861,3 +1859,51 @@ macro BranchIfFastJSArrayForCopy(o: Object, context: Context): never
|
||||
macro IsFastJSArrayWithNoCustomIteration(context: Context, o: Object): bool {
|
||||
return Is<FastJSArrayWithNoCustomIteration>(o);
|
||||
}
|
||||
|
||||
extern transitioning runtime
|
||||
CreateDataProperty(implicit context: Context)(JSReceiver, Object, Object);
|
||||
|
||||
transitioning builtin FastCreateDataProperty(implicit context: Context)(
|
||||
receiver: JSReceiver, key: Object, value: Object): Object {
|
||||
try {
|
||||
let array = Cast<FastJSArray>(receiver) otherwise Slow;
|
||||
const index: Smi = Cast<Smi>(key) otherwise goto Slow;
|
||||
if (index < 0 || index > array.length) goto Slow;
|
||||
array::EnsureWriteableFastElements(array);
|
||||
const isAppend = index == array.length;
|
||||
const kind = array.map.elements_kind;
|
||||
// We may have to transition a.
|
||||
// For now, if transition is required, jump away to slow.
|
||||
if (IsFastSmiElementsKind(kind)) {
|
||||
const smiValue = Cast<Smi>(value) otherwise Slow;
|
||||
if (isAppend) {
|
||||
BuildAppendJSArray(HOLEY_SMI_ELEMENTS, array, value) otherwise Slow;
|
||||
} else {
|
||||
const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
|
||||
elements[index] = smiValue;
|
||||
}
|
||||
} else if (IsDoubleElementsKind(kind)) {
|
||||
const numberValue = Cast<Number>(value) otherwise Slow;
|
||||
if (isAppend) {
|
||||
BuildAppendJSArray(HOLEY_DOUBLE_ELEMENTS, array, value)
|
||||
otherwise Slow;
|
||||
} else {
|
||||
const doubleElements = Cast<FixedDoubleArray>(array.elements)
|
||||
otherwise unreachable;
|
||||
doubleElements[index] = numberValue;
|
||||
}
|
||||
} else {
|
||||
assert(IsFastSmiOrTaggedElementsKind(kind));
|
||||
if (isAppend) {
|
||||
BuildAppendJSArray(HOLEY_ELEMENTS, array, value) otherwise Slow;
|
||||
} else {
|
||||
const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
|
||||
elements[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
label Slow {
|
||||
CreateDataProperty(receiver, key, value);
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace object {
|
||||
// Symbol.toPrimitive, toString, and valueOf, which could
|
||||
// invalidate assumptions about the iterable.
|
||||
if (Is<JSReceiver>(pair.key)) goto IfSlow;
|
||||
CreateDataProperty(result, pair.key, pair.value);
|
||||
FastCreateDataProperty(result, pair.key, pair.value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -55,7 +55,7 @@ namespace object {
|
||||
iterator::IteratorValue(step, fastIteratorResultMap);
|
||||
const pair: KeyValuePair =
|
||||
collections::LoadKeyValuePair(iteratorValue);
|
||||
CreateDataProperty(result, pair.key, pair.value);
|
||||
FastCreateDataProperty(result, pair.key, pair.value);
|
||||
}
|
||||
return result;
|
||||
} catch (e) deferred {
|
||||
|
@ -980,6 +980,14 @@ static bool TransitivelyCalledBuiltinHasNoSideEffect(Builtins::Name caller,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case Builtins::kFastCreateDataProperty:
|
||||
switch (caller) {
|
||||
case Builtins::kArrayPrototypeSlice:
|
||||
case Builtins::kArrayFilter:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case Builtins::kSetProperty:
|
||||
switch (caller) {
|
||||
case Builtins::kArrayPrototypeSlice:
|
||||
|
Loading…
Reference in New Issue
Block a user