blob: fe416fa4a24289464537901ac2e27b61f1e065a7 [file] [log] [blame]
// Copyright 2018 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 {
macro LoadWithHoleCheck<Elements : type extends FixedArrayBase>(
elements: FixedArrayBase, index: Smi): JSAny
labels IfHole;
LoadWithHoleCheck<FixedArray>(implicit context: Context)(
elements: FixedArrayBase, index: Smi): JSAny
labels IfHole {
const elements: FixedArray = UnsafeCast<FixedArray>(elements);
const element: Object = elements.objects[index];
if (element == TheHole) goto IfHole;
return UnsafeCast<JSAny>(element);
}
LoadWithHoleCheck<FixedDoubleArray>(implicit context: Context)(
elements: FixedArrayBase, index: Smi): JSAny
labels IfHole {
const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
const element: float64 = elements.floats[index].Value() otherwise IfHole;
return AllocateHeapNumberWithValue(element);
}
macro FastArrayLastIndexOf<Elements : type extends FixedArrayBase>(
context: Context, array: JSArray, from: Smi, searchElement: JSAny): Smi {
const elements: FixedArrayBase = array.elements;
let k: Smi = from;
// Bug(898785): Due to side-effects in the evaluation of `fromIndex`
// the {from} can be out-of-bounds here, so we need to clamp {k} to
// the {elements} length. We might be reading holes / hole NaNs still
// due to that, but those will be ignored below.
if (k >= elements.length) {
k = elements.length - 1;
}
while (k >= 0) {
try {
const element: JSAny = LoadWithHoleCheck<Elements>(elements, k)
otherwise Hole;
const same: Boolean = StrictEqual(searchElement, element);
if (same == True) {
assert(Is<FastJSArray>(array));
return k;
}
} label Hole {} // Do nothing for holes.
--k;
}
assert(Is<FastJSArray>(array));
return -1;
}
transitioning macro
GetFromIndex(context: Context, length: Number, arguments: Arguments): Number {
// 4. If fromIndex is present, let n be ? ToInteger(fromIndex);
// else let n be len - 1.
const n: Number =
arguments.length < 2 ? length - 1 : ToInteger_Inline(arguments[1]);
// 5. If n >= 0, then.
let k: Number = SmiConstant(0);
if (n >= 0) {
// a. If n is -0, let k be +0; else let k be min(n, len - 1).
// If n was -0 it got truncated to 0.0, so taking the minimum is fine.
k = Min(n, length - 1);
} else {
// a. Let k be len + n.
k = length + n;
}
return k;
}
macro TryFastArrayLastIndexOf(
context: Context, receiver: JSReceiver, searchElement: JSAny,
from: Number): JSAny
labels Slow {
const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;
const length: Smi = array.length;
if (length == 0) return SmiConstant(-1);
const fromSmi: Smi = Cast<Smi>(from) otherwise Slow;
const kind: ElementsKind = array.map.elements_kind;
if (IsFastSmiOrTaggedElementsKind(kind)) {
return FastArrayLastIndexOf<FixedArray>(
context, array, fromSmi, searchElement);
}
assert(IsDoubleElementsKind(kind));
return FastArrayLastIndexOf<FixedDoubleArray>(
context, array, fromSmi, searchElement);
}
transitioning macro GenericArrayLastIndexOf(
context: Context, object: JSReceiver, searchElement: JSAny,
from: Number): JSAny {
let k: Number = from;
// 7. Repeat, while k >= 0.
while (k >= 0) {
// a. Let kPresent be ? HasProperty(O, ! ToString(k)).
const kPresent: Boolean = HasProperty(object, k);
// b. If kPresent is true, then.
if (kPresent == True) {
// i. Let elementK be ? Get(O, ! ToString(k)).
const element: JSAny = GetProperty(object, k);
// ii. Let same be the result of performing Strict Equality Comparison
// searchElement === elementK.
const same: Boolean = StrictEqual(searchElement, element);
// iii. If same is true, return k.
if (same == True) return k;
}
// c. Decrease k by 1.
--k;
}
// 8. Return -1.
return SmiConstant(-1);
}
// https://tc39.github.io/ecma262/#sec-array.prototype.lastIndexOf
transitioning javascript builtin ArrayPrototypeLastIndexOf(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
// 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver);
// 2. Let len be ? ToLength(? Get(O, "length")).
const length: Number = GetLengthProperty(object);
// 3. If len is 0, return -1.
if (length == SmiConstant(0)) return SmiConstant(-1);
// Step 4 - 6.
const from: Number = GetFromIndex(context, length, arguments);
const searchElement: JSAny = arguments[0];
try {
return TryFastArrayLastIndexOf(context, object, searchElement, from)
otherwise Baseline;
} label Baseline {
return GenericArrayLastIndexOf(context, object, searchElement, from);
}
}
}