diff options
Diffstat (limited to 'deps/v8/src/builtins/array-lastindexof.tq')
-rw-r--r-- | deps/v8/src/builtins/array-lastindexof.tq | 159 |
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); + } + } +} |