// Copyright 2017 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/ic/handler-configuration.h"

#include "src/code-stubs.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/transitions.h"

namespace v8 {
namespace internal {

namespace {

template <bool fill_array = true>
int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
                        Handle<JSReceiver> holder, Handle<Name> name,
                        Handle<FixedArray> array, int first_index) {
  if (!holder.is_null() && holder->map() == *receiver_map) return 0;

  HandleScope scope(isolate);
  int checks_count = 0;

  if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
    // The validity cell check for primitive and global proxy receivers does
    // not guarantee that certain native context ever had access to other
    // native context. However, a handler created for one native context could
    // be used in other native context through the megamorphic stub cache.
    // So we record the original native context to which this handler
    // corresponds.
    if (fill_array) {
      Handle<Context> native_context = isolate->native_context();
      array->set(first_index + checks_count, native_context->self_weak_cell());
    }
    checks_count++;

  } else if (receiver_map->IsJSGlobalObjectMap()) {
    // If we are creating a handler for [Load/Store]GlobalIC then we need to
    // check that the property did not appear in the global object.
    if (fill_array) {
      Handle<JSGlobalObject> global = isolate->global_object();
      Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
          global, name, PropertyCellType::kInvalidated);
      DCHECK(cell->value()->IsTheHole(isolate));
      Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
      array->set(first_index + checks_count, *weak_cell);
    }
    checks_count++;
  }

  // Create/count entries for each global or dictionary prototype appeared in
  // the prototype chain contains from receiver till holder.
  PrototypeIterator::WhereToEnd end = name->IsPrivate()
                                          ? PrototypeIterator::END_AT_NON_HIDDEN
                                          : PrototypeIterator::END_AT_NULL;
  for (PrototypeIterator iter(receiver_map, end); !iter.IsAtEnd();
       iter.Advance()) {
    Handle<JSReceiver> current =
        PrototypeIterator::GetCurrent<JSReceiver>(iter);
    if (holder.is_identical_to(current)) break;
    Handle<Map> current_map(current->map(), isolate);

    if (current_map->IsJSGlobalObjectMap()) {
      if (fill_array) {
        Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
        Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
            global, name, PropertyCellType::kInvalidated);
        DCHECK(cell->value()->IsTheHole(isolate));
        Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
        array->set(first_index + checks_count, *weak_cell);
      }
      checks_count++;

    } else if (current_map->is_dictionary_map()) {
      DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
      if (fill_array) {
        DCHECK_EQ(NameDictionary::kNotFound,
                  current->property_dictionary()->FindEntry(name));
        Handle<WeakCell> weak_cell =
            Map::GetOrCreatePrototypeWeakCell(current, isolate);
        array->set(first_index + checks_count, *weak_cell);
      }
      checks_count++;
    }
  }
  return checks_count;
}

// Returns 0 if the validity cell check is enough to ensure that the
// prototype chain from |receiver_map| till |holder| did not change.
// If the |holder| is an empty handle then the full prototype chain is
// checked.
// Returns -1 if the handler has to be compiled or the number of prototype
// checks otherwise.
int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
                           Handle<JSReceiver> holder, Handle<Name> name) {
  return InitPrototypeChecks<false>(isolate, receiver_map, holder, name,
                                    Handle<FixedArray>(), 0);
}

enum class HolderCellRequest {
  kGlobalPropertyCell,
  kHolder,
};

Handle<WeakCell> HolderCell(Isolate* isolate, Handle<JSReceiver> holder,
                            Handle<Name> name, HolderCellRequest request) {
  if (request == HolderCellRequest::kGlobalPropertyCell) {
    DCHECK(holder->IsJSGlobalObject());
    Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder);
    GlobalDictionary* dict = global->global_dictionary();
    int number = dict->FindEntry(name);
    DCHECK_NE(NameDictionary::kNotFound, number);
    Handle<PropertyCell> cell(dict->CellAt(number), isolate);
    return isolate->factory()->NewWeakCell(cell);
  }
  return Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}

}  // namespace

// static
Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
                                              Handle<Map> receiver_map,
                                              Handle<JSReceiver> holder,
                                              Handle<Name> name,
                                              Handle<Smi> smi_handler) {
  int checks_count =
      GetPrototypeCheckCount(isolate, receiver_map, holder, name);
  DCHECK_LE(0, checks_count);

  if (receiver_map->IsPrimitiveMap() ||
      receiver_map->is_access_check_needed()) {
    DCHECK(!receiver_map->is_dictionary_map());
    DCHECK_LE(1, checks_count);  // For native context.
    smi_handler = EnableAccessCheckOnReceiver(isolate, smi_handler);
  } else if (receiver_map->is_dictionary_map() &&
             !receiver_map->IsJSGlobalObjectMap()) {
    smi_handler = EnableLookupOnReceiver(isolate, smi_handler);
  }

  Handle<Cell> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  DCHECK(!validity_cell.is_null());

  // LoadIC dispatcher expects PropertyCell as a "holder" in case of kGlobal
  // handler kind.
  HolderCellRequest request = GetHandlerKind(*smi_handler) == kGlobal
                                  ? HolderCellRequest::kGlobalPropertyCell
                                  : HolderCellRequest::kHolder;

  Handle<WeakCell> holder_cell = HolderCell(isolate, holder, name, request);

  if (checks_count == 0) {
    return isolate->factory()->NewTuple3(holder_cell, smi_handler,
                                         validity_cell, TENURED);
  }
  Handle<FixedArray> handler_array(isolate->factory()->NewFixedArray(
      kFirstPrototypeIndex + checks_count, TENURED));
  handler_array->set(kSmiHandlerIndex, *smi_handler);
  handler_array->set(kValidityCellIndex, *validity_cell);
  handler_array->set(kHolderCellIndex, *holder_cell);
  InitPrototypeChecks(isolate, receiver_map, holder, name, handler_array,
                      kFirstPrototypeIndex);
  return handler_array;
}

// static
Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
                                          Handle<Map> receiver_map,
                                          Handle<Object> holder,
                                          Handle<Name> name,
                                          Handle<Smi> smi_handler) {
  Handle<JSReceiver> end;  // null handle
  int checks_count = GetPrototypeCheckCount(isolate, receiver_map, end, name);
  DCHECK_LE(0, checks_count);

  if (receiver_map->IsPrimitiveMap() ||
      receiver_map->is_access_check_needed()) {
    DCHECK(!receiver_map->is_dictionary_map());
    DCHECK_LE(1, checks_count);  // For native context.
    smi_handler = EnableAccessCheckOnReceiver(isolate, smi_handler);
  } else if (receiver_map->is_dictionary_map() &&
             !receiver_map->IsJSGlobalObjectMap()) {
    smi_handler = EnableLookupOnReceiver(isolate, smi_handler);
  }

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  if (validity_cell.is_null()) {
    DCHECK_EQ(0, checks_count);
    // Lookup on receiver isn't supported in case of a simple smi handler.
    if (!LookupOnReceiverBits::decode(smi_handler->value())) return smi_handler;
    validity_cell = handle(Smi::kZero, isolate);
  }

  Factory* factory = isolate->factory();
  if (checks_count == 0) {
    return factory->NewTuple3(holder, smi_handler, validity_cell, TENURED);
  }
  Handle<FixedArray> handler_array(factory->NewFixedArray(
      LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
  handler_array->set(kSmiHandlerIndex, *smi_handler);
  handler_array->set(kValidityCellIndex, *validity_cell);
  handler_array->set(kHolderCellIndex, *holder);
  InitPrototypeChecks(isolate, receiver_map, end, name, handler_array,
                      kFirstPrototypeIndex);
  return handler_array;
}

// static
Handle<Object> StoreHandler::StoreElementTransition(
    Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
    KeyedAccessStoreMode store_mode) {
  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
  ElementsKind elements_kind = receiver_map->elements_kind();
  Handle<Code> stub = ElementsTransitionAndStoreStub(
                          isolate, elements_kind, transition->elements_kind(),
                          is_js_array, store_mode)
                          .GetCode();
  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  if (validity_cell.is_null()) {
    validity_cell = handle(Smi::kZero, isolate);
  }
  Handle<WeakCell> cell = Map::WeakCellForMap(transition);
  return isolate->factory()->NewTuple3(cell, stub, validity_cell, TENURED);
}

// static
Handle<Object> StoreHandler::StoreTransition(Isolate* isolate,
                                             Handle<Map> receiver_map,
                                             Handle<JSObject> holder,
                                             Handle<Map> transition,
                                             Handle<Name> name) {
  Handle<Object> smi_handler;
  if (transition->is_dictionary_map()) {
    smi_handler = StoreNormal(isolate);
  } else {
    int descriptor = transition->LastAdded();
    Handle<DescriptorArray> descriptors(transition->instance_descriptors());
    PropertyDetails details = descriptors->GetDetails(descriptor);
    Representation representation = details.representation();
    DCHECK(!representation.IsNone());

    // Declarative handlers don't support access checks.
    DCHECK(!transition->is_access_check_needed());

    DCHECK_EQ(kData, details.kind());
    if (details.location() == kDescriptor) {
      smi_handler = TransitionToConstant(isolate, descriptor);

    } else {
      DCHECK_EQ(kField, details.location());
      bool extend_storage =
          Map::cast(transition->GetBackPointer())->unused_property_fields() ==
          0;

      FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
      smi_handler = TransitionToField(isolate, descriptor, index,
                                      representation, extend_storage);
    }
  }
  // |holder| is either a receiver if the property is non-existent or
  // one of the prototypes.
  DCHECK(!holder.is_null());
  bool is_nonexistent = holder->map() == transition->GetBackPointer();
  if (is_nonexistent) holder = Handle<JSObject>::null();

  int checks_count =
      GetPrototypeCheckCount(isolate, receiver_map, holder, name);

  DCHECK_LE(0, checks_count);
  DCHECK(!receiver_map->IsJSGlobalObjectMap());

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  if (validity_cell.is_null()) {
    DCHECK_EQ(0, checks_count);
    validity_cell = handle(Smi::kZero, isolate);
  }

  Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition);

  Factory* factory = isolate->factory();
  if (checks_count == 0) {
    return factory->NewTuple3(transition_cell, smi_handler, validity_cell,
                              TENURED);
  }
  Handle<FixedArray> handler_array(
      factory->NewFixedArray(kFirstPrototypeIndex + checks_count, TENURED));
  handler_array->set(kSmiHandlerIndex, *smi_handler);
  handler_array->set(kValidityCellIndex, *validity_cell);
  handler_array->set(kTransitionCellIndex, *transition_cell);
  InitPrototypeChecks(isolate, receiver_map, holder, name, handler_array,
                      kFirstPrototypeIndex);
  return handler_array;
}

// static
Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
                                        Handle<Map> receiver_map,
                                        Handle<JSProxy> proxy,
                                        Handle<JSReceiver> receiver,
                                        Handle<Name> name) {
  Handle<Object> smi_handler = StoreProxy(isolate);

  if (receiver.is_identical_to(proxy)) return smi_handler;

  int checks_count = GetPrototypeCheckCount(isolate, receiver_map, proxy, name);

  DCHECK_LE(0, checks_count);

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  if (validity_cell.is_null()) {
    DCHECK_EQ(0, checks_count);
    validity_cell = handle(Smi::kZero, isolate);
  }

  Factory* factory = isolate->factory();
  Handle<WeakCell> holder_cell = factory->NewWeakCell(proxy);

  if (checks_count == 0) {
    return factory->NewTuple3(holder_cell, smi_handler, validity_cell, TENURED);
  }
  Handle<FixedArray> handler_array(
      factory->NewFixedArray(kFirstPrototypeIndex + checks_count, TENURED));
  handler_array->set(kSmiHandlerIndex, *smi_handler);
  handler_array->set(kValidityCellIndex, *validity_cell);
  handler_array->set(kTransitionCellIndex, *holder_cell);
  InitPrototypeChecks(isolate, receiver_map, proxy, name, handler_array,
                      kFirstPrototypeIndex);
  return handler_array;
}

Object* StoreHandler::ValidHandlerOrNull(Object* raw_handler, Name* name,
                                         Handle<Map>* out_transition) {
  STATIC_ASSERT(kValidityCellOffset == Tuple3::kValue3Offset);

  Smi* valid = Smi::FromInt(Map::kPrototypeChainValid);

  if (raw_handler->IsTuple3()) {
    // Check validity cell.
    Tuple3* handler = Tuple3::cast(raw_handler);

    Object* raw_validity_cell = handler->value3();
    // |raw_valitity_cell| can be Smi::kZero if no validity cell is required
    // (which counts as valid).
    if (raw_validity_cell->IsCell() &&
        Cell::cast(raw_validity_cell)->value() != valid) {
      return nullptr;
    }

  } else {
    DCHECK(raw_handler->IsFixedArray());
    FixedArray* handler = FixedArray::cast(raw_handler);

    // Check validity cell.
    Object* value = Cell::cast(handler->get(kValidityCellIndex))->value();
    if (value != valid) return nullptr;

    // Check prototypes.
    Heap* heap = handler->GetHeap();
    Isolate* isolate = heap->isolate();
    Handle<Name> name_handle(name, isolate);
    for (int i = kFirstPrototypeIndex; i < handler->length(); i++) {
      // This mirrors AccessorAssembler::CheckPrototype.
      WeakCell* prototype_cell = WeakCell::cast(handler->get(i));
      if (prototype_cell->cleared()) return nullptr;
      HeapObject* maybe_prototype = HeapObject::cast(prototype_cell->value());
      if (maybe_prototype->IsPropertyCell()) {
        Object* value = PropertyCell::cast(maybe_prototype)->value();
        if (value != heap->the_hole_value()) return nullptr;
      } else {
        DCHECK(maybe_prototype->map()->is_dictionary_map());
        // Do a negative dictionary lookup.
        NameDictionary* dict =
            JSObject::cast(maybe_prototype)->property_dictionary();
        int number = dict->FindEntry(isolate, name_handle);
        if (number != NameDictionary::kNotFound) {
          PropertyDetails details = dict->DetailsAt(number);
          if (details.IsReadOnly() || details.kind() == kAccessor) {
            return nullptr;
          }
          break;
        }
      }
    }
  }

  // Check if the transition target is deprecated.
  WeakCell* target_cell = GetTransitionCell(raw_handler);
  Map* transition = Map::cast(target_cell->value());
  if (transition->is_deprecated()) return nullptr;
  *out_transition = handle(transition);
  return raw_handler;
}

}  // namespace internal
}  // namespace v8
