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

#ifndef V8_LAYOUT_DESCRIPTOR_INL_H_
#define V8_LAYOUT_DESCRIPTOR_INL_H_

#include "src/layout-descriptor.h"

namespace v8 {
namespace internal {

LayoutDescriptor* LayoutDescriptor::FromSmi(Smi* smi) {
  return LayoutDescriptor::cast(smi);
}


Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) {
  if (length <= kSmiValueSize) {
    // The whole bit vector fits into a smi.
    return handle(LayoutDescriptor::FromSmi(Smi::kZero), isolate);
  }
  int backing_store_length = GetSlowModeBackingStoreLength(length);
  Handle<LayoutDescriptor> result = Handle<LayoutDescriptor>::cast(
      isolate->factory()->NewByteArray(backing_store_length, TENURED));
  memset(reinterpret_cast<void*>(result->GetDataStartAddress()), 0,
         result->DataSize());
  return result;
}


bool LayoutDescriptor::InobjectUnboxedField(int inobject_properties,
                                            PropertyDetails details) {
  if (details.location() != kField || !details.representation().IsDouble()) {
    return false;
  }
  // We care only about in-object properties.
  return details.field_index() < inobject_properties;
}


LayoutDescriptor* LayoutDescriptor::FastPointerLayout() {
  return LayoutDescriptor::FromSmi(Smi::kZero);
}


bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
                                  int* layout_bit_index) {
  if (static_cast<unsigned>(field_index) >= static_cast<unsigned>(capacity())) {
    return false;
  }

  *layout_word_index = field_index / kBitsPerLayoutWord;
  CHECK((!IsSmi() && (*layout_word_index < length())) ||
        (IsSmi() && (*layout_word_index < 1)));

  *layout_bit_index = field_index % kBitsPerLayoutWord;
  return true;
}


LayoutDescriptor* LayoutDescriptor::SetRawData(int field_index) {
  return SetTagged(field_index, false);
}


LayoutDescriptor* LayoutDescriptor::SetTagged(int field_index, bool tagged) {
  int layout_word_index = 0;
  int layout_bit_index = 0;

  CHECK(GetIndexes(field_index, &layout_word_index, &layout_bit_index));
  uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;

  if (IsSlowLayout()) {
    uint32_t value = get_layout_word(layout_word_index);
    if (tagged) {
      value &= ~layout_mask;
    } else {
      value |= layout_mask;
    }
    set_layout_word(layout_word_index, value);
    return this;
  } else {
    uint32_t value = static_cast<uint32_t>(Smi::ToInt(this));
    if (tagged) {
      value &= ~layout_mask;
    } else {
      value |= layout_mask;
    }
    return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value)));
  }
}


bool LayoutDescriptor::IsTagged(int field_index) {
  if (IsFastPointerLayout()) return true;

  int layout_word_index;
  int layout_bit_index;

  if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
    // All bits after Out of bounds queries
    return true;
  }
  uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;

  if (IsSlowLayout()) {
    uint32_t value = get_layout_word(layout_word_index);
    return (value & layout_mask) == 0;
  } else {
    uint32_t value = static_cast<uint32_t>(Smi::ToInt(this));
    return (value & layout_mask) == 0;
  }
}


bool LayoutDescriptor::IsFastPointerLayout() {
  return this == FastPointerLayout();
}


bool LayoutDescriptor::IsFastPointerLayout(Object* layout_descriptor) {
  return layout_descriptor == FastPointerLayout();
}


bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }


int LayoutDescriptor::capacity() {
  return IsSlowLayout() ? (length() * kBitsPerByte) : kSmiValueSize;
}


LayoutDescriptor* LayoutDescriptor::cast_gc_safe(Object* object) {
  // The map word of the object can be a forwarding pointer during
  // object evacuation phase of GC. Since the layout descriptor methods
  // for checking whether a field is tagged or not do not depend on the
  // object map, it should be safe.
  return reinterpret_cast<LayoutDescriptor*>(object);
}

int LayoutDescriptor::GetSlowModeBackingStoreLength(int length) {
  DCHECK_LT(0, length);
  // We allocate kPointerSize rounded blocks of memory anyway so we increase
  // the length  of allocated array to utilize that "lost" space which could
  // also help to avoid layout descriptor reallocations.
  return RoundUp(length, kBitsPerByte * kPointerSize) / kBitsPerByte;
}


int LayoutDescriptor::CalculateCapacity(Map* map, DescriptorArray* descriptors,
                                        int num_descriptors) {
  int inobject_properties = map->GetInObjectProperties();
  if (inobject_properties == 0) return 0;

  DCHECK_LE(num_descriptors, descriptors->number_of_descriptors());

  int layout_descriptor_length;
  const int kMaxWordsPerField = kDoubleSize / kPointerSize;

  if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) {
    // Even in the "worst" case (all fields are doubles) it would fit into
    // a Smi, so no need to calculate length.
    layout_descriptor_length = kSmiValueSize;

  } else {
    layout_descriptor_length = 0;

    for (int i = 0; i < num_descriptors; i++) {
      PropertyDetails details = descriptors->GetDetails(i);
      if (!InobjectUnboxedField(inobject_properties, details)) continue;
      int field_index = details.field_index();
      int field_width_in_words = details.field_width_in_words();
      layout_descriptor_length =
          Max(layout_descriptor_length, field_index + field_width_in_words);
    }
  }
  layout_descriptor_length = Min(layout_descriptor_length, inobject_properties);
  return layout_descriptor_length;
}


LayoutDescriptor* LayoutDescriptor::Initialize(
    LayoutDescriptor* layout_descriptor, Map* map, DescriptorArray* descriptors,
    int num_descriptors) {
  DisallowHeapAllocation no_allocation;
  int inobject_properties = map->GetInObjectProperties();

  for (int i = 0; i < num_descriptors; i++) {
    PropertyDetails details = descriptors->GetDetails(i);
    if (!InobjectUnboxedField(inobject_properties, details)) {
      DCHECK(details.location() != kField ||
             layout_descriptor->IsTagged(details.field_index()));
      continue;
    }
    int field_index = details.field_index();
    layout_descriptor = layout_descriptor->SetRawData(field_index);
    if (details.field_width_in_words() > 1) {
      layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
    }
  }
  return layout_descriptor;
}


// LayoutDescriptorHelper is a helper class for querying whether inobject
// property at offset is Double or not.
LayoutDescriptorHelper::LayoutDescriptorHelper(Map* map)
    : all_fields_tagged_(true),
      header_size_(0),
      layout_descriptor_(LayoutDescriptor::FastPointerLayout()) {
  if (!FLAG_unbox_double_fields) return;

  layout_descriptor_ = map->layout_descriptor_gc_safe();
  if (layout_descriptor_->IsFastPointerLayout()) {
    return;
  }

  header_size_ = map->GetInObjectPropertiesStartInWords() * kPointerSize;
  DCHECK_GE(header_size_, 0);

  all_fields_tagged_ = false;
}


bool LayoutDescriptorHelper::IsTagged(int offset_in_bytes) {
  DCHECK(IsAligned(offset_in_bytes, kPointerSize));
  if (all_fields_tagged_) return true;
  // Object headers do not contain non-tagged fields.
  if (offset_in_bytes < header_size_) return true;
  int field_index = (offset_in_bytes - header_size_) / kPointerSize;

  return layout_descriptor_->IsTagged(field_index);
}
}  // namespace internal
}  // namespace v8

#endif  // V8_LAYOUT_DESCRIPTOR_INL_H_
