// 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 MapBitFields1 extends uint8 {
  has_non_instance_prototype: bool: 1 bit;
  is_callable: bool: 1 bit;
  has_named_interceptor: bool: 1 bit;
  has_indexed_interceptor: bool: 1 bit;
  is_undetectable: bool: 1 bit;
  is_access_check_needed: bool: 1 bit;
  is_constructor: bool: 1 bit;
  has_prototype_slot: bool: 1 bit;
}

bitfield struct MapBitFields2 extends uint8 {
  new_target_is_base: bool: 1 bit;
  is_immutable_prototype: bool: 1 bit;
  unused: bool: 1 bit;
  elements_kind: ElementsKind: 5 bit;
}

bitfield struct MapBitFields3 extends uint32 {
  enum_length: int32: 10 bit;
  number_of_own_descriptors: int32: 10 bit;
  is_prototype_map: bool: 1 bit;
  is_dictionary_map: bool: 1 bit;
  owns_descriptors: bool: 1 bit;
  is_in_retained_map_list: bool: 1 bit;
  is_deprecated: bool: 1 bit;
  is_unstable: bool: 1 bit;
  is_migration_target: bool: 1 bit;
  is_extensible: bool: 1 bit;
  may_have_interesting_symbols: bool: 1 bit;
  construction_counter: int32: 3 bit;
}

extern class Map extends HeapObject {
  macro PrototypeInfo(): PrototypeInfo labels HasNoPrototypeInfo {
    typeswitch (this.transitions_or_prototype_info) {
      case (Weak<Map>): {
        goto HasNoPrototypeInfo;
      }
      case (Smi): {
        goto HasNoPrototypeInfo;
      }
      case (info: PrototypeInfo): {
        return info;
      }
      case (Map | TransitionArray): {
        goto HasNoPrototypeInfo;
      }
    }
  }

  instance_size_in_words: uint8;
  in_object_properties_start_or_constructor_function_index: uint8;
  used_or_unused_instance_size_in_words: uint8;
  visitor_id: uint8;
  instance_type: InstanceType;
  bit_field: MapBitFields1;
  bit_field2: MapBitFields2;
  bit_field3: MapBitFields3;

  @if(TAGGED_SIZE_8_BYTES) optional_padding: uint32;
  @ifnot(TAGGED_SIZE_8_BYTES) optional_padding: void;

  prototype: JSReceiver|Null;
  constructor_or_back_pointer_or_native_context: Object;
  instance_descriptors: DescriptorArray;
  @if(V8_DOUBLE_FIELDS_UNBOXING) layout_descriptor: LayoutDescriptor;
  @ifnot(V8_DOUBLE_FIELDS_UNBOXING) layout_descriptor: void;
  dependent_code: DependentCode;
  prototype_validity_cell: Smi|Cell;
  weak transitions_or_prototype_info: Map|Weak<Map>|TransitionArray|
      PrototypeInfo|Smi;
}

@export
macro LoadMapPrototypeInfo(m: Map): PrototypeInfo labels HasNoPrototypeInfo {
  return m.PrototypeInfo() otherwise HasNoPrototypeInfo;
}

// Returns true if the map corresponds to non-special fast or dictionary
// object.
@export
macro IsSimpleObjectMap(map: Map): bool {
  if (IsSpecialReceiverInstanceType(map.instance_type)) {
    return false;
  }
  const bitField = map.bit_field;
  return !bitField.has_named_interceptor & !bitField.is_access_check_needed;
}

extern macro IsSpecialReceiverInstanceType(InstanceType): bool;