// 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.

#include 'src/builtins/builtins-array-gen.h'

namespace array {
// Naming convention from elements.cc. We have a similar intent but implement
// fastpaths using generics instead of using a class hierarchy for elements
// kinds specific implementations.
type GenericElementsAccessor extends ElementsKind;
type FastPackedSmiElements extends ElementsKind;
type FastPackedObjectElements extends ElementsKind;
type FastPackedDoubleElements extends ElementsKind;
type FastSmiOrObjectElements extends ElementsKind;
type FastDoubleElements extends ElementsKind;
type DictionaryElements extends ElementsKind;

macro EnsureWriteableFastElements(implicit context: Context)(array: JSArray) {
  assert(IsFastElementsKind(array.map.elements_kind));

  const elements: FixedArrayBase = array.elements;
  if (elements.map != kCOWMap) return;

  // There are no COW *_DOUBLE_ELEMENTS arrays, so we are allowed to always
  // extract FixedArrays and don't have to worry about FixedDoubleArrays.
  assert(IsFastSmiOrTaggedElementsKind(array.map.elements_kind));

  const length = Convert<intptr>(Cast<Smi>(array.length) otherwise unreachable);
  array.elements =
      ExtractFixedArray(UnsafeCast<FixedArray>(elements), 0, length, length);
  assert(array.elements.map != kCOWMap);
}

macro LoadElementOrUndefined(implicit context: Context)(
    a: FixedArray, i: Smi): JSAny {
  const e = UnsafeCast<(JSAny | TheHole)>(a.objects[i]);
  return ReplaceTheHoleWithUndefined(e);
}

macro LoadElementOrUndefined(a: FixedDoubleArray, i: Smi): NumberOrUndefined {
  const f: float64 = a.floats[i].Value() otherwise return Undefined;
  return AllocateHeapNumberWithValue(f);
}

macro StoreArrayHole(elements: FixedDoubleArray, k: Smi): void {
  elements.floats[k] = kDoubleHole;
}

macro StoreArrayHole(elements: FixedArray, k: Smi): void {
  elements.objects[k] = TheHole;
}

extern macro SetPropertyLength(implicit context: Context)(JSAny, Number);

const kLengthDescriptorIndex:
    constexpr int31 generates 'JSArray::kLengthDescriptorIndex';
const kAttributesReadOnlyMask: constexpr int31
    generates 'PropertyDetails::kAttributesReadOnlyMask';

@export
macro EnsureArrayLengthWritable(implicit context: Context)(map: Map):
    void labels Bailout {
  // Don't support arrays in dictionary named property mode.
  if (IsDictionaryMap(map)) {
    goto Bailout;
  }

  // Check whether the length property is writable. The length property is the
  // only default named property on arrays. It's nonconfigurable, hence is
  // guaranteed to stay the first property.
  const descriptors: DescriptorArray = map.instance_descriptors;
  const descriptor:&DescriptorEntry =
      &descriptors.descriptors[kLengthDescriptorIndex];
  assert(TaggedEqual(descriptor->key, LengthStringConstant()));
  const details: Smi = UnsafeCast<Smi>(descriptor->details);
  if ((details & kAttributesReadOnlyMask) != 0) {
    goto Bailout;
  }
}

macro CreateJSArrayWithElements(implicit context: Context)(array: FixedArray):
    JSArray {
  const nativeContext: NativeContext = LoadNativeContext(context);
  const map: Map =
      LoadJSArrayElementsMap(ElementsKind::PACKED_ELEMENTS, nativeContext);
  return AllocateJSArray(map, array, array.length);
}
}
