summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/array-lastindexof.tq
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/array-lastindexof.tq')
-rw-r--r--deps/v8/src/builtins/array-lastindexof.tq159
1 files changed, 159 insertions, 0 deletions
diff --git a/deps/v8/src/builtins/array-lastindexof.tq b/deps/v8/src/builtins/array-lastindexof.tq
new file mode 100644
index 0000000000..056220092e
--- /dev/null
+++ b/deps/v8/src/builtins/array-lastindexof.tq
@@ -0,0 +1,159 @@
+// 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.
+
+module array {
+ macro LoadWithHoleCheck<Elements: type>(
+ elements: FixedArrayBase, index: Smi): Object
+ labels IfHole;
+
+ LoadWithHoleCheck<FixedArray>(elements: FixedArrayBase, index: Smi): Object
+ labels IfHole {
+ const elements: FixedArray = UnsafeCast<FixedArray>(elements);
+ const element: Object = elements[index];
+ if (element == Hole) goto IfHole;
+ return element;
+ }
+
+ LoadWithHoleCheck<FixedDoubleArray>(elements: FixedArrayBase, index: Smi):
+ Object
+ labels IfHole {
+ const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
+ const element: float64 = LoadDoubleWithHoleCheck(elements, index)
+ otherwise IfHole;
+ return AllocateHeapNumberWithValue(element);
+ }
+
+ macro FastArrayLastIndexOf<Elements: type>(
+ context: Context, array: JSArray, from: Smi, searchElement: Object): 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: Object = LoadWithHoleCheck<Elements>(elements, k)
+ otherwise Hole;
+
+ const same: Boolean = StrictEqual(searchElement, element);
+ if (same == True) {
+ assert(IsFastJSArray(array, context));
+ return k;
+ }
+ }
+ label Hole {} // Do nothing for holes.
+
+ --k;
+ }
+
+ assert(IsFastJSArray(array, context));
+ return -1;
+ }
+
+ macro GetFromIndex(
+ context: Context, length: Number,
+ arguments: constexpr 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(context, arguments[1], kTruncateMinusZero);
+
+ // 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: Object,
+ from: Number): Object
+ labels Slow {
+ EnsureFastJSArray(context, receiver) otherwise Slow;
+ const array: JSArray = UnsafeCast<JSArray>(receiver);
+
+ const length: Smi = array.length_fast;
+ 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);
+ }
+
+ macro GenericArrayLastIndexOf(
+ context: Context, object: JSReceiver, searchElement: Object,
+ from: Number): Object {
+ let k: Number = from;
+
+ // 7. Repeat, while k >= 0.
+ while (k >= 0) {
+ // a. Let kPresent be ? HasProperty(O, ! ToString(k)).
+ const kPresent: Boolean = HasProperty(context, object, k);
+
+ // b. If kPresent is true, then.
+ if (kPresent == True) {
+ // i. Let elementK be ? Get(O, ! ToString(k)).
+ const element: Object = GetProperty(context, 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
+ javascript builtin ArrayPrototypeLastIndexOf(
+ context: Context, receiver: Object, ...arguments): Object {
+ // 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(context, 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: Object = arguments[0];
+
+ try {
+ return TryFastArrayLastIndexOf(context, object, searchElement, from)
+ otherwise Baseline;
+ }
+ label Baseline {
+ return GenericArrayLastIndexOf(context, object, searchElement, from);
+ }
+ }
+}