// Copyright 2012 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/transitions.h"

#include "src/objects-inl.h"
#include "src/transitions-inl.h"
#include "src/utils.h"

namespace v8 {
namespace internal {

void TransitionsAccessor::Initialize() {
  raw_transitions_ = map_->raw_transitions();
  HeapObject* heap_object;
  if (raw_transitions_->IsSmi() ||
      raw_transitions_->IsClearedWeakHeapObject()) {
    encoding_ = kUninitialized;
  } else if (raw_transitions_->IsWeakHeapObject()) {
    encoding_ = kWeakRef;
  } else if (raw_transitions_->ToStrongHeapObject(&heap_object)) {
    if (heap_object->IsTransitionArray()) {
      encoding_ = kFullTransitionArray;
    } else {
      DCHECK(heap_object->IsPrototypeInfo());
      encoding_ = kPrototypeInfo;
    }
  } else {
    UNREACHABLE();
  }
#if DEBUG
  needs_reload_ = false;
#endif
}

Map* TransitionsAccessor::GetSimpleTransition() {
  switch (encoding()) {
    case kWeakRef:
      return Map::cast(raw_transitions_->ToWeakHeapObject());
    default:
      return nullptr;
  }
}

bool TransitionsAccessor::HasSimpleTransitionTo(Map* map) {
  switch (encoding()) {
    case kWeakRef:
      return raw_transitions_->ToWeakHeapObject() == map;
    case kPrototypeInfo:
    case kUninitialized:
    case kFullTransitionArray:
      return false;
  }
  UNREACHABLE();
}

void TransitionsAccessor::Insert(Handle<Name> name, Handle<Map> target,
                                 SimpleTransitionFlag flag) {
  DCHECK(!map_handle_.is_null());
  target->SetBackPointer(map_);

  // If the map doesn't have any transitions at all yet, install the new one.
  if (encoding() == kUninitialized) {
    if (flag == SIMPLE_PROPERTY_TRANSITION) {
      ReplaceTransitions(HeapObjectReference::Weak(*target));
      return;
    }
    // If the flag requires a full TransitionArray, allocate one.
    Handle<TransitionArray> result =
        isolate_->factory()->NewTransitionArray(0, 1);
    ReplaceTransitions(MaybeObject::FromObject(*result));
    Reload();
  }

  bool is_special_transition = flag == SPECIAL_TRANSITION;
  // If the map has a simple transition, check if it should be overwritten.
  Map* simple_transition = GetSimpleTransition();
  if (simple_transition != nullptr) {
    Name* key = GetSimpleTransitionKey(simple_transition);
    PropertyDetails old_details = GetSimpleTargetDetails(simple_transition);
    PropertyDetails new_details =
        is_special_transition ? PropertyDetails::Empty()
                              : GetTargetDetails(isolate_, *name, *target);
    if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) &&
        old_details.kind() == new_details.kind() &&
        old_details.attributes() == new_details.attributes()) {
      ReplaceTransitions(HeapObjectReference::Weak(*target));
      return;
    }
    // Otherwise allocate a full TransitionArray with slack for a new entry.
    Handle<Map> map(simple_transition, isolate_);
    Handle<TransitionArray> result =
        isolate_->factory()->NewTransitionArray(1, 1);
    // Reload state; allocations might have caused it to be cleared.
    Reload();
    simple_transition = GetSimpleTransition();
    if (simple_transition != nullptr) {
      DCHECK_EQ(*map, simple_transition);
      if (encoding_ == kWeakRef) {
        result->Set(0, GetSimpleTransitionKey(simple_transition),
                    HeapObjectReference::Weak(simple_transition));
      } else {
        UNREACHABLE();
      }
    } else {
      result->SetNumberOfTransitions(0);
    }
    ReplaceTransitions(MaybeObject::FromObject(*result));
    Reload();
  }

  // At this point, we know that the map has a full TransitionArray.
  DCHECK_EQ(kFullTransitionArray, encoding());

  int number_of_transitions = 0;
  int new_nof = 0;
  int insertion_index = kNotFound;
  DCHECK_EQ(is_special_transition, IsSpecialTransition(isolate_, *name));
  PropertyDetails details = is_special_transition
                                ? PropertyDetails::Empty()
                                : GetTargetDetails(isolate_, *name, *target);

  {
    DisallowHeapAllocation no_gc;
    TransitionArray* array = transitions();
    number_of_transitions = array->number_of_transitions();
    new_nof = number_of_transitions;

    int index =
        is_special_transition
            ? array->SearchSpecial(Symbol::cast(*name), &insertion_index)
            : array->Search(isolate_, details.kind(), *name,
                            details.attributes(), &insertion_index);
    // If an existing entry was found, overwrite it and return.
    if (index != kNotFound) {
      array->SetRawTarget(index, HeapObjectReference::Weak(*target));
      return;
    }

    ++new_nof;
    CHECK_LE(new_nof, kMaxNumberOfTransitions);
    DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);

    // If there is enough capacity, insert new entry into the existing array.
    if (new_nof <= array->Capacity()) {
      array->SetNumberOfTransitions(new_nof);
      for (index = number_of_transitions; index > insertion_index; --index) {
        array->SetKey(index, array->GetKey(index - 1));
        array->SetRawTarget(index, array->GetRawTarget(index - 1));
      }
      array->SetKey(index, *name);
      array->SetRawTarget(index, HeapObjectReference::Weak(*target));
      SLOW_DCHECK(array->IsSortedNoDuplicates(isolate_));
      return;
    }
  }

  // We're gonna need a bigger TransitionArray.
  Handle<TransitionArray> result = isolate_->factory()->NewTransitionArray(
      new_nof,
      Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions));

  // The map's transition array may have shrunk during the allocation above as
  // it was weakly traversed, though it is guaranteed not to disappear. Trim the
  // result copy if needed, and recompute variables.
  Reload();
  DisallowHeapAllocation no_gc;
  TransitionArray* array = transitions();
  if (array->number_of_transitions() != number_of_transitions) {
    DCHECK(array->number_of_transitions() < number_of_transitions);

    number_of_transitions = array->number_of_transitions();
    new_nof = number_of_transitions;

    insertion_index = kNotFound;
    int index =
        is_special_transition
            ? array->SearchSpecial(Symbol::cast(*name), &insertion_index)
            : array->Search(isolate_, details.kind(), *name,
                            details.attributes(), &insertion_index);
    if (index == kNotFound) {
      ++new_nof;
    } else {
      insertion_index = index;
    }
    DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);

    result->SetNumberOfTransitions(new_nof);
  }

  if (array->HasPrototypeTransitions()) {
    result->SetPrototypeTransitions(array->GetPrototypeTransitions());
  }

  DCHECK_NE(kNotFound, insertion_index);
  for (int i = 0; i < insertion_index; ++i) {
    result->Set(i, array->GetKey(i), array->GetRawTarget(i));
  }
  result->Set(insertion_index, *name, HeapObjectReference::Weak(*target));
  for (int i = insertion_index; i < number_of_transitions; ++i) {
    result->Set(i + 1, array->GetKey(i), array->GetRawTarget(i));
  }

  SLOW_DCHECK(result->IsSortedNoDuplicates(isolate_));
  ReplaceTransitions(MaybeObject::FromObject(*result));
}

Map* TransitionsAccessor::SearchTransition(Name* name, PropertyKind kind,
                                           PropertyAttributes attributes) {
  DCHECK(name->IsUniqueName());
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      return nullptr;
    case kWeakRef: {
      Map* map = Map::cast(raw_transitions_->ToWeakHeapObject());
      if (!IsMatchingMap(map, name, kind, attributes)) return nullptr;
      return map;
    }
    case kFullTransitionArray: {
      int transition = transitions()->Search(isolate_, kind, name, attributes);
      if (transition == kNotFound) return nullptr;
      return transitions()->GetTarget(transition);
    }
  }
  UNREACHABLE();
}

Map* TransitionsAccessor::SearchSpecial(Symbol* name) {
  if (encoding() != kFullTransitionArray) return nullptr;
  int transition = transitions()->SearchSpecial(name);
  if (transition == kNotFound) return nullptr;
  return transitions()->GetTarget(transition);
}

// static
bool TransitionsAccessor::IsSpecialTransition(Isolate* isolate, Name* name) {
  if (!name->IsSymbol()) return false;
  Heap* heap = isolate->heap();
  return name == heap->nonextensible_symbol() ||
         name == heap->sealed_symbol() || name == heap->frozen_symbol() ||
         name == heap->elements_transition_symbol() ||
         name == heap->strict_function_transition_symbol();
}

MaybeHandle<Map> TransitionsAccessor::FindTransitionToDataProperty(
    Handle<Name> name, RequestedLocation requested_location) {
  DCHECK(name->IsUniqueName());
  DisallowHeapAllocation no_gc;
  PropertyAttributes attributes = name->IsPrivate() ? DONT_ENUM : NONE;
  Map* target = SearchTransition(*name, kData, attributes);
  if (target == nullptr) return MaybeHandle<Map>();
  PropertyDetails details = target->GetLastDescriptorDetails();
  DCHECK_EQ(attributes, details.attributes());
  DCHECK_EQ(kData, details.kind());
  if (requested_location == kFieldOnly && details.location() != kField) {
    return MaybeHandle<Map>();
  }
  return Handle<Map>(target, isolate_);
}

Handle<String> TransitionsAccessor::ExpectedTransitionKey() {
  DisallowHeapAllocation no_gc;
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
    case kFullTransitionArray:
      return Handle<String>::null();
    case kWeakRef: {
      Map* target = Map::cast(raw_transitions_->ToWeakHeapObject());
      PropertyDetails details = GetSimpleTargetDetails(target);
      if (details.location() != kField) return Handle<String>::null();
      DCHECK_EQ(kData, details.kind());
      if (details.attributes() != NONE) return Handle<String>::null();
      Name* name = GetSimpleTransitionKey(target);
      if (!name->IsString()) return Handle<String>::null();
      return handle(String::cast(name), isolate_);
    }
  }
  UNREACHABLE();
}

Handle<Map> TransitionsAccessor::ExpectedTransitionTarget() {
  DCHECK(!ExpectedTransitionKey().is_null());
  return handle(GetTarget(0), isolate_);
}

bool TransitionsAccessor::CanHaveMoreTransitions() {
  if (map_->is_dictionary_map()) return false;
  if (encoding() == kFullTransitionArray) {
    return transitions()->number_of_transitions() < kMaxNumberOfTransitions;
  }
  return true;
}

// static
bool TransitionsAccessor::IsMatchingMap(Map* target, Name* name,
                                        PropertyKind kind,
                                        PropertyAttributes attributes) {
  int descriptor = target->LastAdded();
  DescriptorArray* descriptors = target->instance_descriptors();
  Name* key = descriptors->GetKey(descriptor);
  if (key != name) return false;
  PropertyDetails details = descriptors->GetDetails(descriptor);
  return (details.kind() == kind && details.attributes() == attributes);
}

// static
bool TransitionArray::CompactPrototypeTransitionArray(Isolate* isolate,
                                                      WeakFixedArray* array) {
  const int header = kProtoTransitionHeaderSize;
  int number_of_transitions = NumberOfPrototypeTransitions(array);
  if (number_of_transitions == 0) {
    // Empty array cannot be compacted.
    return false;
  }
  int new_number_of_transitions = 0;
  for (int i = 0; i < number_of_transitions; i++) {
    MaybeObject* target = array->Get(header + i);
    DCHECK(target->IsClearedWeakHeapObject() ||
           (target->IsWeakHeapObject() && target->ToWeakHeapObject()->IsMap()));
    if (!target->IsClearedWeakHeapObject()) {
      if (new_number_of_transitions != i) {
        array->Set(header + new_number_of_transitions, target);
      }
      new_number_of_transitions++;
    }
  }
  // Fill slots that became free with undefined value.
  MaybeObject* undefined =
      MaybeObject::FromObject(*isolate->factory()->undefined_value());
  for (int i = new_number_of_transitions; i < number_of_transitions; i++) {
    array->Set(header + i, undefined);
  }
  if (number_of_transitions != new_number_of_transitions) {
    SetNumberOfPrototypeTransitions(array, new_number_of_transitions);
  }
  return new_number_of_transitions < number_of_transitions;
}


// static
Handle<WeakFixedArray> TransitionArray::GrowPrototypeTransitionArray(
    Handle<WeakFixedArray> array, int new_capacity, Isolate* isolate) {
  // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
  int capacity = array->length() - kProtoTransitionHeaderSize;
  new_capacity = Min(kMaxCachedPrototypeTransitions, new_capacity);
  DCHECK_GT(new_capacity, capacity);
  int grow_by = new_capacity - capacity;
  array =
      isolate->factory()->CopyWeakFixedArrayAndGrow(array, grow_by, TENURED);
  if (capacity < 0) {
    // There was no prototype transitions array before, so the size
    // couldn't be copied. Initialize it explicitly.
    SetNumberOfPrototypeTransitions(*array, 0);
  }
  return array;
}

void TransitionsAccessor::PutPrototypeTransition(Handle<Object> prototype,
                                                 Handle<Map> target_map) {
  DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
  // Don't cache prototype transition if this map is either shared, or a map of
  // a prototype.
  if (map_->is_prototype_map()) return;
  if (map_->is_dictionary_map() || !FLAG_cache_prototype_transitions) return;

  const int header = TransitionArray::kProtoTransitionHeaderSize;

  Handle<WeakFixedArray> cache(GetPrototypeTransitions(), isolate_);
  int capacity = cache->length() - header;
  int transitions = TransitionArray::NumberOfPrototypeTransitions(*cache) + 1;

  if (transitions > capacity) {
    // Grow the array if compacting it doesn't free space.
    if (!TransitionArray::CompactPrototypeTransitionArray(isolate_, *cache)) {
      if (capacity == TransitionArray::kMaxCachedPrototypeTransitions) return;
      cache = TransitionArray::GrowPrototypeTransitionArray(
          cache, 2 * transitions, isolate_);
      Reload();
      SetPrototypeTransitions(cache);
    }
  }

  // Reload number of transitions as they might have been compacted.
  int last = TransitionArray::NumberOfPrototypeTransitions(*cache);
  int entry = header + last;

  cache->Set(entry, HeapObjectReference::Weak(*target_map));
  TransitionArray::SetNumberOfPrototypeTransitions(*cache, last + 1);
}

Handle<Map> TransitionsAccessor::GetPrototypeTransition(
    Handle<Object> prototype) {
  DisallowHeapAllocation no_gc;
  WeakFixedArray* cache = GetPrototypeTransitions();
  int length = TransitionArray::NumberOfPrototypeTransitions(cache);
  for (int i = 0; i < length; i++) {
    MaybeObject* target =
        cache->Get(TransitionArray::kProtoTransitionHeaderSize + i);
    DCHECK(target->IsClearedWeakHeapObject() || target->IsWeakHeapObject());
    if (!target->IsClearedWeakHeapObject()) {
      Map* map = Map::cast(target->ToWeakHeapObject());
      if (map->prototype() == *prototype) {
        return handle(map, isolate_);
      }
    }
  }
  return Handle<Map>();
}

WeakFixedArray* TransitionsAccessor::GetPrototypeTransitions() {
  if (encoding() != kFullTransitionArray ||
      !transitions()->HasPrototypeTransitions()) {
    return isolate_->heap()->empty_weak_fixed_array();
  }
  return transitions()->GetPrototypeTransitions();
}

// static
void TransitionArray::SetNumberOfPrototypeTransitions(
    WeakFixedArray* proto_transitions, int value) {
  DCHECK_NE(proto_transitions->length(), 0);
  proto_transitions->Set(kProtoTransitionNumberOfEntriesOffset,
                         MaybeObject::FromSmi(Smi::FromInt(value)));
}

int TransitionsAccessor::NumberOfTransitions() {
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      return 0;
    case kWeakRef:
      return 1;
    case kFullTransitionArray:
      return transitions()->number_of_transitions();
  }
  UNREACHABLE();
  return 0;  // Make GCC happy.
}

void TransitionArray::Zap(Isolate* isolate) {
  MemsetPointer(data_start() + kPrototypeTransitionsIndex,
                MaybeObject::FromObject(isolate->heap()->the_hole_value()),
                length() - kPrototypeTransitionsIndex);
  SetNumberOfTransitions(0);
}

void TransitionsAccessor::ReplaceTransitions(MaybeObject* new_transitions) {
  if (encoding() == kFullTransitionArray) {
    TransitionArray* old_transitions = transitions();
#if DEBUG
    CheckNewTransitionsAreConsistent(old_transitions,
                                     new_transitions->ToStrongHeapObject());
    DCHECK(old_transitions != new_transitions->ToStrongHeapObject());
#endif
    // Transition arrays are not shared. When one is replaced, it should not
    // keep referenced objects alive, so we zap it.
    // When there is another reference to the array somewhere (e.g. a handle),
    // not zapping turns from a waste of memory into a source of crashes.
    old_transitions->Zap(isolate_);
  }
  map_->set_raw_transitions(new_transitions);
  MarkNeedsReload();
}

void TransitionsAccessor::SetPrototypeTransitions(
    Handle<WeakFixedArray> proto_transitions) {
  EnsureHasFullTransitionArray();
  transitions()->SetPrototypeTransitions(*proto_transitions);
}

void TransitionsAccessor::EnsureHasFullTransitionArray() {
  if (encoding() == kFullTransitionArray) return;
  int nof = encoding() == kUninitialized ? 0 : 1;
  Handle<TransitionArray> result = isolate_->factory()->NewTransitionArray(nof);
  Reload();  // Reload after possible GC.
  if (nof == 1) {
    if (encoding() == kUninitialized) {
      // If allocation caused GC and cleared the target, trim the new array.
      result->SetNumberOfTransitions(0);
    } else {
      // Otherwise populate the new array.
      Handle<Map> target(GetSimpleTransition(), isolate_);
      Name* key = GetSimpleTransitionKey(*target);
      result->Set(0, key, HeapObjectReference::Weak(*target));
    }
  }
  ReplaceTransitions(MaybeObject::FromObject(*result));
  Reload();  // Reload after replacing transitions.
}

void TransitionsAccessor::TraverseTransitionTreeInternal(
    TraverseCallback callback, void* data, DisallowHeapAllocation* no_gc) {
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      break;
    case kWeakRef: {
      Map* simple_target = Map::cast(raw_transitions_->ToWeakHeapObject());
      TransitionsAccessor(isolate_, simple_target, no_gc)
          .TraverseTransitionTreeInternal(callback, data, no_gc);
      break;
    }
    case kFullTransitionArray: {
      if (transitions()->HasPrototypeTransitions()) {
        WeakFixedArray* proto_trans = transitions()->GetPrototypeTransitions();
        int length = TransitionArray::NumberOfPrototypeTransitions(proto_trans);
        for (int i = 0; i < length; ++i) {
          int index = TransitionArray::kProtoTransitionHeaderSize + i;
          MaybeObject* target = proto_trans->Get(index);
          DCHECK(target->IsClearedWeakHeapObject() ||
                 target->IsWeakHeapObject());
          if (target->IsClearedWeakHeapObject()) continue;
          TransitionsAccessor(isolate_, Map::cast(target->ToWeakHeapObject()),
                              no_gc)
              .TraverseTransitionTreeInternal(callback, data, no_gc);
        }
      }
      for (int i = 0; i < transitions()->number_of_transitions(); ++i) {
        TransitionsAccessor(isolate_, transitions()->GetTarget(i), no_gc)
            .TraverseTransitionTreeInternal(callback, data, no_gc);
      }
      break;
    }
  }
  callback(map_, data);
}

#ifdef DEBUG
void TransitionsAccessor::CheckNewTransitionsAreConsistent(
    TransitionArray* old_transitions, Object* transitions) {
  // This function only handles full transition arrays.
  DCHECK_EQ(kFullTransitionArray, encoding());
  TransitionArray* new_transitions = TransitionArray::cast(transitions);
  for (int i = 0; i < old_transitions->number_of_transitions(); i++) {
    Map* target = old_transitions->GetTarget(i);
    if (target->instance_descriptors() == map_->instance_descriptors()) {
      Name* key = old_transitions->GetKey(i);
      int new_target_index;
      if (IsSpecialTransition(isolate_, key)) {
        new_target_index = new_transitions->SearchSpecial(Symbol::cast(key));
      } else {
        PropertyDetails details = GetTargetDetails(isolate_, key, target);
        new_target_index = new_transitions->Search(isolate_, details.kind(),
                                                   key, details.attributes());
      }
      DCHECK_NE(TransitionArray::kNotFound, new_target_index);
      DCHECK_EQ(target, new_transitions->GetTarget(new_target_index));
    }
  }
}
#endif

// Private non-static helper functions (operating on full transition arrays).

int TransitionArray::SearchDetails(Isolate* isolate, int transition,
                                   PropertyKind kind,
                                   PropertyAttributes attributes,
                                   int* out_insertion_index) {
  int nof_transitions = number_of_transitions();
  DCHECK(transition < nof_transitions);
  Name* key = GetKey(transition);
  for (; transition < nof_transitions && GetKey(transition) == key;
       transition++) {
    Map* target = GetTarget(transition);
    PropertyDetails target_details =
        TransitionsAccessor::GetTargetDetails(isolate, key, target);

    int cmp = CompareDetails(kind, attributes, target_details.kind(),
                             target_details.attributes());
    if (cmp == 0) {
      return transition;
    } else if (cmp < 0) {
      break;
    }
  }
  if (out_insertion_index != nullptr) *out_insertion_index = transition;
  return kNotFound;
}

int TransitionArray::Search(Isolate* isolate, PropertyKind kind, Name* name,
                            PropertyAttributes attributes,
                            int* out_insertion_index) {
  int transition = SearchName(name, out_insertion_index);
  if (transition == kNotFound) return kNotFound;
  return SearchDetails(isolate, transition, kind, attributes,
                       out_insertion_index);
}

void TransitionArray::Sort(Isolate* isolate) {
  DisallowHeapAllocation no_gc;
  // In-place insertion sort.
  int length = number_of_transitions();
  for (int i = 1; i < length; i++) {
    Name* key = GetKey(i);
    MaybeObject* target = GetRawTarget(i);
    PropertyKind kind = kData;
    PropertyAttributes attributes = NONE;
    if (!TransitionsAccessor::IsSpecialTransition(isolate, key)) {
      Map* target_map = TransitionsAccessor::GetTargetFromRaw(target);
      PropertyDetails details =
          TransitionsAccessor::GetTargetDetails(isolate, key, target_map);
      kind = details.kind();
      attributes = details.attributes();
    }
    int j;
    for (j = i - 1; j >= 0; j--) {
      Name* temp_key = GetKey(j);
      MaybeObject* temp_target = GetRawTarget(j);
      PropertyKind temp_kind = kData;
      PropertyAttributes temp_attributes = NONE;
      if (!TransitionsAccessor::IsSpecialTransition(isolate, temp_key)) {
        Map* temp_target_map =
            TransitionsAccessor::GetTargetFromRaw(temp_target);
        PropertyDetails details = TransitionsAccessor::GetTargetDetails(
            isolate, temp_key, temp_target_map);
        temp_kind = details.kind();
        temp_attributes = details.attributes();
      }
      int cmp =
          CompareKeys(temp_key, temp_key->Hash(), temp_kind, temp_attributes,
                      key, key->Hash(), kind, attributes);
      if (cmp > 0) {
        SetKey(j + 1, temp_key);
        SetRawTarget(j + 1, temp_target);
      } else {
        break;
      }
    }
    SetKey(j + 1, key);
    SetRawTarget(j + 1, target);
  }
  DCHECK(IsSortedNoDuplicates(isolate));
}

}  // namespace internal
}  // namespace v8
