11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cinamespace array {
61cb0ef41Sopenharmony_cimacro LoadElement<ElementsAccessor : type extends ElementsKind, T: type>(
71cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi): T;
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciLoadElement<array::FastPackedSmiElements, Smi>(implicit context: Context)(
101cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi): Smi {
111cb0ef41Sopenharmony_ci  const elements: FixedArray = UnsafeCast<FixedArray>(elements);
121cb0ef41Sopenharmony_ci  return UnsafeCast<Smi>(elements.objects[index]);
131cb0ef41Sopenharmony_ci}
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciLoadElement<array::FastPackedObjectElements, JSAny>(implicit context: Context)(
161cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi): JSAny {
171cb0ef41Sopenharmony_ci  const elements: FixedArray = UnsafeCast<FixedArray>(elements);
181cb0ef41Sopenharmony_ci  return UnsafeCast<JSAny>(elements.objects[index]);
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciLoadElement<array::FastPackedDoubleElements, float64>(
221cb0ef41Sopenharmony_ci    implicit context: Context)(elements: FixedArrayBase, index: Smi): float64 {
231cb0ef41Sopenharmony_ci  const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
241cb0ef41Sopenharmony_ci  // This macro is only used for PACKED_DOUBLE, loading the hole should
251cb0ef41Sopenharmony_ci  // be impossible.
261cb0ef41Sopenharmony_ci  return elements.floats[index].Value() otherwise unreachable;
271cb0ef41Sopenharmony_ci}
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cimacro StoreElement<ElementsAccessor : type extends ElementsKind, T: type>(
301cb0ef41Sopenharmony_ci    implicit context: Context)(
311cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi, value: T): void;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciStoreElement<array::FastPackedSmiElements, Smi>(implicit context: Context)(
341cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi, value: Smi): void {
351cb0ef41Sopenharmony_ci  const elems: FixedArray = UnsafeCast<FixedArray>(elements);
361cb0ef41Sopenharmony_ci  StoreFixedArrayElement(elems, index, value);
371cb0ef41Sopenharmony_ci}
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciStoreElement<array::FastPackedObjectElements, JSAny>(implicit context: Context)(
401cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi, value: JSAny): void {
411cb0ef41Sopenharmony_ci  const elements: FixedArray = UnsafeCast<FixedArray>(elements);
421cb0ef41Sopenharmony_ci  elements.objects[index] = value;
431cb0ef41Sopenharmony_ci}
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciStoreElement<array::FastPackedDoubleElements, float64>(
461cb0ef41Sopenharmony_ci    implicit context: Context)(
471cb0ef41Sopenharmony_ci    elements: FixedArrayBase, index: Smi, value: float64): void {
481cb0ef41Sopenharmony_ci  const elems: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
491cb0ef41Sopenharmony_ci  StoreFixedDoubleArrayElement(elems, index, value);
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci// Fast-path for all PACKED_* elements kinds. These do not need to check
531cb0ef41Sopenharmony_ci// whether a property is present, so we can simply swap them using fast
541cb0ef41Sopenharmony_ci// FixedArray loads/stores.
551cb0ef41Sopenharmony_cimacro FastPackedArrayReverse<Accessor: type, T: type>(
561cb0ef41Sopenharmony_ci    implicit context: Context)(elements: FixedArrayBase, length: Smi): void {
571cb0ef41Sopenharmony_ci  let lower: Smi = 0;
581cb0ef41Sopenharmony_ci  let upper: Smi = length - 1;
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  while (lower < upper) {
611cb0ef41Sopenharmony_ci    const lowerValue: T = LoadElement<Accessor, T>(elements, lower);
621cb0ef41Sopenharmony_ci    const upperValue: T = LoadElement<Accessor, T>(elements, upper);
631cb0ef41Sopenharmony_ci    StoreElement<Accessor>(elements, lower, upperValue);
641cb0ef41Sopenharmony_ci    StoreElement<Accessor>(elements, upper, lowerValue);
651cb0ef41Sopenharmony_ci    ++lower;
661cb0ef41Sopenharmony_ci    --upper;
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci}
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_citransitioning macro GenericArrayReverse(
711cb0ef41Sopenharmony_ci    context: Context, receiver: JSAny): JSAny {
721cb0ef41Sopenharmony_ci  // 1. Let O be ? ToObject(this value).
731cb0ef41Sopenharmony_ci  const object: JSReceiver = ToObject_Inline(context, receiver);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  // 2. Let len be ? ToLength(? Get(O, "length")).
761cb0ef41Sopenharmony_ci  const length: Number = GetLengthProperty(object);
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  // 3. Let middle be floor(len / 2).
791cb0ef41Sopenharmony_ci  // 4. Let lower be 0.
801cb0ef41Sopenharmony_ci  // 5. Repeat, while lower != middle.
811cb0ef41Sopenharmony_ci  //   a. Let upper be len - lower - 1.
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // Instead of calculating the middle value, we simply initialize upper
841cb0ef41Sopenharmony_ci  // with len - 1 and decrement it after each iteration.
851cb0ef41Sopenharmony_ci  let lower: Number = 0;
861cb0ef41Sopenharmony_ci  let upper: Number = length - 1;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  while (lower < upper) {
891cb0ef41Sopenharmony_ci    let lowerValue: JSAny = Undefined;
901cb0ef41Sopenharmony_ci    let upperValue: JSAny = Undefined;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    // b. Let upperP be ! ToString(upper).
931cb0ef41Sopenharmony_ci    // c. Let lowerP be ! ToString(lower).
941cb0ef41Sopenharmony_ci    // d. Let lowerExists be ? HasProperty(O, lowerP).
951cb0ef41Sopenharmony_ci    const lowerExists: Boolean = HasProperty(object, lower);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci    // e. If lowerExists is true, then.
981cb0ef41Sopenharmony_ci    if (lowerExists == True) {
991cb0ef41Sopenharmony_ci      // i. Let lowerValue be ? Get(O, lowerP).
1001cb0ef41Sopenharmony_ci      lowerValue = GetProperty(object, lower);
1011cb0ef41Sopenharmony_ci    }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci    // f. Let upperExists be ? HasProperty(O, upperP).
1041cb0ef41Sopenharmony_ci    const upperExists: Boolean = HasProperty(object, upper);
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    // g. If upperExists is true, then.
1071cb0ef41Sopenharmony_ci    if (upperExists == True) {
1081cb0ef41Sopenharmony_ci      // i. Let upperValue be ? Get(O, upperP).
1091cb0ef41Sopenharmony_ci      upperValue = GetProperty(object, upper);
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci    // h. If lowerExists is true and upperExists is true, then
1131cb0ef41Sopenharmony_ci    if (lowerExists == True && upperExists == True) {
1141cb0ef41Sopenharmony_ci      // i. Perform ? Set(O, lowerP, upperValue, true).
1151cb0ef41Sopenharmony_ci      SetProperty(object, lower, upperValue);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci      // ii. Perform ? Set(O, upperP, lowerValue, true).
1181cb0ef41Sopenharmony_ci      SetProperty(object, upper, lowerValue);
1191cb0ef41Sopenharmony_ci    } else if (lowerExists == False && upperExists == True) {
1201cb0ef41Sopenharmony_ci      // i. Perform ? Set(O, lowerP, upperValue, true).
1211cb0ef41Sopenharmony_ci      SetProperty(object, lower, upperValue);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci      // ii. Perform ? DeletePropertyOrThrow(O, upperP).
1241cb0ef41Sopenharmony_ci      DeleteProperty(object, upper, LanguageMode::kStrict);
1251cb0ef41Sopenharmony_ci    } else if (lowerExists == True && upperExists == False) {
1261cb0ef41Sopenharmony_ci      // i. Perform ? DeletePropertyOrThrow(O, lowerP).
1271cb0ef41Sopenharmony_ci      DeleteProperty(object, lower, LanguageMode::kStrict);
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci      // ii. Perform ? Set(O, upperP, lowerValue, true).
1301cb0ef41Sopenharmony_ci      SetProperty(object, upper, lowerValue);
1311cb0ef41Sopenharmony_ci    }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    // l. Increase lower by 1.
1341cb0ef41Sopenharmony_ci    ++lower;
1351cb0ef41Sopenharmony_ci    --upper;
1361cb0ef41Sopenharmony_ci  }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  // 6. Return O.
1391cb0ef41Sopenharmony_ci  return object;
1401cb0ef41Sopenharmony_ci}
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_cimacro TryFastPackedArrayReverse(implicit context: Context)(receiver: JSAny):
1431cb0ef41Sopenharmony_ci    void labels Slow {
1441cb0ef41Sopenharmony_ci  const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  const kind: ElementsKind = array.map.elements_kind;
1471cb0ef41Sopenharmony_ci  if (kind == ElementsKind::PACKED_SMI_ELEMENTS) {
1481cb0ef41Sopenharmony_ci    array::EnsureWriteableFastElements(array);
1491cb0ef41Sopenharmony_ci    FastPackedArrayReverse<array::FastPackedSmiElements, Smi>(
1501cb0ef41Sopenharmony_ci        array.elements, array.length);
1511cb0ef41Sopenharmony_ci  } else if (kind == ElementsKind::PACKED_ELEMENTS) {
1521cb0ef41Sopenharmony_ci    array::EnsureWriteableFastElements(array);
1531cb0ef41Sopenharmony_ci    FastPackedArrayReverse<array::FastPackedObjectElements, JSAny>(
1541cb0ef41Sopenharmony_ci        array.elements, array.length);
1551cb0ef41Sopenharmony_ci  } else if (kind == ElementsKind::PACKED_DOUBLE_ELEMENTS) {
1561cb0ef41Sopenharmony_ci    FastPackedArrayReverse<array::FastPackedDoubleElements, float64>(
1571cb0ef41Sopenharmony_ci        array.elements, array.length);
1581cb0ef41Sopenharmony_ci  } else {
1591cb0ef41Sopenharmony_ci    goto Slow;
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci}
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci// https://tc39.github.io/ecma262/#sec-array.prototype.reverse
1641cb0ef41Sopenharmony_citransitioning javascript builtin ArrayPrototypeReverse(
1651cb0ef41Sopenharmony_ci    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
1661cb0ef41Sopenharmony_ci  try {
1671cb0ef41Sopenharmony_ci    TryFastPackedArrayReverse(receiver) otherwise Baseline;
1681cb0ef41Sopenharmony_ci    return receiver;
1691cb0ef41Sopenharmony_ci  } label Baseline {
1701cb0ef41Sopenharmony_ci    return GenericArrayReverse(context, receiver);
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci}
174