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

bitfield struct JSArrayBufferFlags extends uint32 {
  is_external: bool: 1 bit;
  is_detachable: bool: 1 bit;
  was_detached: bool: 1 bit;
  is_asm_js_memory: bool: 1 bit;
  is_shared: bool: 1 bit;
  is_resizable: bool: 1 bit;
}

extern class JSArrayBuffer extends JSObjectWithEmbedderSlots {
  byte_length: uintptr;
  max_byte_length: uintptr;
  // A SandboxedPtr if the sandbox is enabled
  backing_store: RawPtr;
  extension: RawPtr;
  bit_field: JSArrayBufferFlags;
  // Pads header size to be a multiple of kTaggedSize.
  @if(TAGGED_SIZE_8_BYTES) optional_padding: uint32;
  @ifnot(TAGGED_SIZE_8_BYTES) optional_padding: void;
}

extern operator '.backing_store_ptr' macro LoadJSArrayBufferBackingStorePtr(
    JSArrayBuffer): RawPtr;

@export
macro IsDetachedBuffer(buffer: JSArrayBuffer): bool {
  return buffer.bit_field.was_detached;
}

@export
macro IsSharedArrayBuffer(buffer: JSArrayBuffer): bool {
  return buffer.bit_field.is_shared;
}

@export
macro IsResizableArrayBuffer(buffer: JSArrayBuffer): bool {
  return buffer.bit_field.is_resizable;
}

// We have 4 different DataViews & TypedArrays:
// 1) Normal (backed by AB / SAB) or non-length tracking backed by GSAB (can't
// go oob once constructed)
// 2) Non-length tracking backed by RAB (can go oob once constructed)
// 3) Length-tracking backed by RAB (JSArrayBuffer stores the length)
// 4) Length-tracking backed by GSAB (BackingStore stores the length)
bitfield struct JSArrayBufferViewFlags extends uint32 {
  is_length_tracking: bool: 1 bit;
  is_backed_by_rab: bool: 1 bit;
}

@abstract
extern class JSArrayBufferView extends JSObjectWithEmbedderSlots {
  buffer: JSArrayBuffer;
  byte_offset: uintptr;
  byte_length: uintptr;
  bit_field: JSArrayBufferViewFlags;
  // Pads header size to be a multiple of kTaggedSize.
  @if(TAGGED_SIZE_8_BYTES) optional_padding: uint32;
  @ifnot(TAGGED_SIZE_8_BYTES) optional_padding: void;
}

@export
macro IsVariableLengthJSArrayBufferView(array: JSArrayBufferView): bool {
  return array.bit_field.is_length_tracking || array.bit_field.is_backed_by_rab;
}

@export
macro IsLengthTrackingJSArrayBufferView(array: JSArrayBufferView): bool {
  return array.bit_field.is_length_tracking;
}

extern macro LoadVariableLengthJSArrayBufferViewByteLength(
    JSArrayBufferView, JSArrayBuffer): uintptr labels DetachedOrOutOfBounds;

macro LoadJSArrayBufferViewByteLength(
    view: JSArrayBufferView,
    buffer: JSArrayBuffer): uintptr labels DetachedOrOutOfBounds {
  if (IsVariableLengthJSArrayBufferView(view)) {
    return LoadVariableLengthJSArrayBufferViewByteLength(view, buffer)
        otherwise DetachedOrOutOfBounds;
  }
  if (IsDetachedBuffer(buffer)) goto DetachedOrOutOfBounds;
  return view.byte_length;
}

extern class JSTypedArray extends JSArrayBufferView {
  length: uintptr;
  // A SandboxedPtr if the sandbox is enabled
  external_pointer: RawPtr;
  base_pointer: ByteArray|Smi;
}

@export
macro IsOnHeapTypedArray(array: JSTypedArray): bool {
  // See JSTypedArray::is_on_heap()
  return TaggedNotEqual(array.base_pointer, SmiConstant(0));
}

extern class JSDataView extends JSArrayBufferView {
  // A SandboxedPtr if the sandbox is enabled
  data_pointer: RawPtr;
}

@abstract
@doNotGenerateCast extern class TypedArrayConstructor extends JSFunction
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Uint8TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Int8TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Uint16TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Int16TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Uint32TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Int32TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Float32TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Float64TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Uint8ClampedTypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Biguint64TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';
@doNotGenerateCast
extern class Bigint64TypedArrayConstructor extends TypedArrayConstructor
    generates 'TNode<JSFunction>';