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

#include "src/layout-descriptor.h"

#include <sstream>

#include "src/base/bits.h"
#include "src/handles-inl.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {

Handle<LayoutDescriptor> LayoutDescriptor::New(
    Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) {
  Isolate* isolate = descriptors->GetIsolate();
  if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate);

  int layout_descriptor_length =
      CalculateCapacity(*map, *descriptors, num_descriptors);

  if (layout_descriptor_length == 0) {
    // No double fields were found, use fast pointer layout.
    return handle(FastPointerLayout(), isolate);
  }

  // Initially, layout descriptor corresponds to an object with all fields
  // tagged.
  Handle<LayoutDescriptor> layout_descriptor_handle =
      LayoutDescriptor::New(isolate, layout_descriptor_length);

  LayoutDescriptor* layout_descriptor = Initialize(
      *layout_descriptor_handle, *map, *descriptors, num_descriptors);

  return handle(layout_descriptor, isolate);
}


Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend(
    Handle<Map> map, PropertyDetails details) {
  DCHECK(map->owns_descriptors());
  Isolate* isolate = map->GetIsolate();
  Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
                                             isolate);

  if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
    DCHECK(details.location() != kField ||
           layout_descriptor->IsTagged(details.field_index()));
    return layout_descriptor;
  }
  int field_index = details.field_index();
  layout_descriptor = LayoutDescriptor::EnsureCapacity(
      isolate, layout_descriptor, field_index + details.field_width_in_words());

  DisallowHeapAllocation no_allocation;
  LayoutDescriptor* layout_desc = *layout_descriptor;
  layout_desc = layout_desc->SetRawData(field_index);
  if (details.field_width_in_words() > 1) {
    layout_desc = layout_desc->SetRawData(field_index + 1);
  }
  return handle(layout_desc, isolate);
}


Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
    Handle<Map> map, PropertyDetails details,
    Handle<LayoutDescriptor> full_layout_descriptor) {
  DisallowHeapAllocation no_allocation;
  LayoutDescriptor* layout_descriptor = map->layout_descriptor();
  if (layout_descriptor->IsSlowLayout()) {
    return full_layout_descriptor;
  }
  if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
    DCHECK(details.location() != kField ||
           layout_descriptor->IsTagged(details.field_index()));
    return handle(layout_descriptor, map->GetIsolate());
  }
  int field_index = details.field_index();
  int new_capacity = field_index + details.field_width_in_words();
  if (new_capacity > layout_descriptor->capacity()) {
    // Current map's layout descriptor runs out of space, so use the full
    // layout descriptor.
    return full_layout_descriptor;
  }

  layout_descriptor = layout_descriptor->SetRawData(field_index);
  if (details.field_width_in_words() > 1) {
    layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
  }
  return handle(layout_descriptor, map->GetIsolate());
}


Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
    Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor,
    int new_capacity) {
  int old_capacity = layout_descriptor->capacity();
  if (new_capacity <= old_capacity) {
    return layout_descriptor;
  }
  Handle<LayoutDescriptor> new_layout_descriptor =
      LayoutDescriptor::New(isolate, new_capacity);
  DCHECK(new_layout_descriptor->IsSlowLayout());

  if (layout_descriptor->IsSlowLayout()) {
    memcpy(new_layout_descriptor->GetDataStartAddress(),
           layout_descriptor->GetDataStartAddress(),
           layout_descriptor->DataSize());
    return new_layout_descriptor;
  } else {
    // Fast layout.
    uint32_t value = static_cast<uint32_t>(Smi::ToInt(*layout_descriptor));
    new_layout_descriptor->set_layout_word(0, value);
    return new_layout_descriptor;
  }
}


bool LayoutDescriptor::IsTagged(int field_index, int max_sequence_length,
                                int* out_sequence_length) {
  DCHECK_GT(max_sequence_length, 0);
  if (IsFastPointerLayout()) {
    *out_sequence_length = max_sequence_length;
    return true;
  }

  int layout_word_index;
  int layout_bit_index;

  if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
    // Out of bounds queries are considered tagged.
    *out_sequence_length = max_sequence_length;
    return true;
  }
  uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;

  uint32_t value = IsSlowLayout() ? get_layout_word(layout_word_index)
                                  : static_cast<uint32_t>(Smi::ToInt(this));

  bool is_tagged = (value & layout_mask) == 0;
  if (!is_tagged) value = ~value;  // Count set bits instead of cleared bits.
  value = value & ~(layout_mask - 1);  // Clear bits we are not interested in.
  int sequence_length =
      base::bits::CountTrailingZeros(value) - layout_bit_index;

  if (layout_bit_index + sequence_length == kBitsPerLayoutWord) {
    // This is a contiguous sequence till the end of current word, proceed
    // counting in the subsequent words.
    if (IsSlowLayout()) {
      ++layout_word_index;
      int num_words = number_of_layout_words();
      for (; layout_word_index < num_words; layout_word_index++) {
        value = get_layout_word(layout_word_index);
        bool cur_is_tagged = (value & 1) == 0;
        if (cur_is_tagged != is_tagged) break;
        if (!is_tagged) value = ~value;  // Count set bits instead.
        int cur_sequence_length = base::bits::CountTrailingZeros(value);
        sequence_length += cur_sequence_length;
        if (sequence_length >= max_sequence_length) break;
        if (cur_sequence_length != kBitsPerLayoutWord) break;
      }
    }
    if (is_tagged && (field_index + sequence_length == capacity())) {
      // The contiguous sequence of tagged fields lasts till the end of the
      // layout descriptor which means that all the fields starting from
      // field_index are tagged.
      sequence_length = std::numeric_limits<int>::max();
    }
  }
  *out_sequence_length = Min(sequence_length, max_sequence_length);
  return is_tagged;
}


Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate,
                                                         int length) {
  return New(isolate, length);
}


LayoutDescriptor* LayoutDescriptor::SetTaggedForTesting(int field_index,
                                                        bool tagged) {
  return SetTagged(field_index, tagged);
}


bool LayoutDescriptorHelper::IsTagged(
    int offset_in_bytes, int end_offset,
    int* out_end_of_contiguous_region_offset) {
  DCHECK(IsAligned(offset_in_bytes, kPointerSize));
  DCHECK(IsAligned(end_offset, kPointerSize));
  DCHECK(offset_in_bytes < end_offset);
  if (all_fields_tagged_) {
    *out_end_of_contiguous_region_offset = end_offset;
    DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
    return true;
  }
  int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize;
  int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize);
  int sequence_length;
  bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length,
                                             &sequence_length);
  DCHECK_GT(sequence_length, 0);
  if (offset_in_bytes < header_size_) {
    // Object headers do not contain non-tagged fields. Check if the contiguous
    // region continues after the header.
    if (tagged) {
      // First field is tagged, calculate end offset from there.
      *out_end_of_contiguous_region_offset =
          header_size_ + sequence_length * kPointerSize;

    } else {
      *out_end_of_contiguous_region_offset = header_size_;
    }
    DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
    return true;
  }
  *out_end_of_contiguous_region_offset =
      offset_in_bytes + sequence_length * kPointerSize;
  DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
  return tagged;
}


LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map,
                                         DescriptorArray* descriptors,
                                         int num_descriptors) {
  DisallowHeapAllocation no_allocation;
  // Fast mode descriptors are never shared and therefore always fully
  // correspond to their map.
  if (!IsSlowLayout()) return this;

  int layout_descriptor_length =
      CalculateCapacity(map, descriptors, num_descriptors);
  // It must not become fast-mode descriptor here, because otherwise it has to
  // be fast pointer layout descriptor already but it's is slow mode now.
  DCHECK_LT(kSmiValueSize, layout_descriptor_length);

  // Trim, clean and reinitialize this slow-mode layout descriptor.
  int new_backing_store_length =
      GetSlowModeBackingStoreLength(layout_descriptor_length);
  int backing_store_length = length();
  if (new_backing_store_length != backing_store_length) {
    DCHECK_LT(new_backing_store_length, backing_store_length);
    int delta = backing_store_length - new_backing_store_length;
    heap->RightTrimFixedArray(this, delta);
  }
  memset(GetDataStartAddress(), 0, DataSize());
  LayoutDescriptor* layout_descriptor =
      Initialize(this, map, descriptors, num_descriptors);
  DCHECK_EQ(this, layout_descriptor);
  return layout_descriptor;
}


bool LayoutDescriptor::IsConsistentWithMap(Map* map, bool check_tail) {
  if (FLAG_unbox_double_fields) {
    DescriptorArray* descriptors = map->instance_descriptors();
    int nof_descriptors = map->NumberOfOwnDescriptors();
    int last_field_index = 0;
    for (int i = 0; i < nof_descriptors; i++) {
      PropertyDetails details = descriptors->GetDetails(i);
      if (details.location() != kField) continue;
      FieldIndex field_index = FieldIndex::ForDescriptor(map, i);
      bool tagged_expected =
          !field_index.is_inobject() || !details.representation().IsDouble();
      for (int bit = 0; bit < details.field_width_in_words(); bit++) {
        bool tagged_actual = IsTagged(details.field_index() + bit);
        DCHECK_EQ(tagged_expected, tagged_actual);
        if (tagged_actual != tagged_expected) return false;
      }
      last_field_index =
          Max(last_field_index,
              details.field_index() + details.field_width_in_words());
    }
    if (check_tail) {
      int n = capacity();
      for (int i = last_field_index; i < n; i++) {
        DCHECK(IsTagged(i));
      }
    }
  }
  return true;
}
}  // namespace internal
}  // namespace v8
