// 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/codegen/code-factory.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/objects/data-handler-inl.h"
#include "src/objects/maybe-object.h"
#include "src/objects/transitions.h"

namespace v8 {
namespace internal {

namespace {

template <typename BitField>
Handle<Smi> SetBitFieldValue(Isolate* isolate, Handle<Smi> smi_handler,
                             typename BitField::FieldType value) {
  int config = smi_handler->value();
  config = BitField::update(config, true);
  return handle(Smi::FromInt(config), isolate);
}

// TODO(ishell): Remove templatezation once we move common bits from
// Load/StoreHandler to the base class.
template <typename ICHandler, bool fill_handler = true>
int InitPrototypeChecksImpl(Isolate* isolate, Handle<ICHandler> handler,
                            Handle<Smi>* smi_handler, Handle<Map> receiver_map,
                            Handle<JSReceiver> holder, MaybeObjectHandle data1,
                            MaybeObjectHandle maybe_data2) {
  int checks_count = 0;
  // Holder-is-receiver case itself does not add entries unless there is an
  // optional data2 value provided.

  if (receiver_map->IsPrimitiveMap() ||
      receiver_map->is_access_check_needed()) {
    DCHECK(!receiver_map->IsJSGlobalObjectMap());
    // 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_handler) {
      Handle<Context> native_context = isolate->native_context();
      handler->set_data2(HeapObjectReference::Weak(*native_context));
    } else {
      // Enable access checks on receiver.
      using Bit = typename ICHandler::DoAccessCheckOnReceiverBits;
      *smi_handler = SetBitFieldValue<Bit>(isolate, *smi_handler, true);
    }
    checks_count++;
  } else if (receiver_map->is_dictionary_map() &&
             !receiver_map->IsJSGlobalObjectMap()) {
    if (!fill_handler) {
      // Enable lookup on receiver.
      using Bit = typename ICHandler::LookupOnReceiverBits;
      *smi_handler = SetBitFieldValue<Bit>(isolate, *smi_handler, true);
    }
  }
  if (fill_handler) {
    handler->set_data1(*data1);
  }
  if (!maybe_data2.is_null()) {
    if (fill_handler) {
      // This value will go either to data2 or data3 slot depending on whether
      // data2 slot is already occupied by native context.
      if (checks_count == 0) {
        handler->set_data2(*maybe_data2);
      } else {
        DCHECK_EQ(1, checks_count);
        handler->set_data3(*maybe_data2);
      }
    }
    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.
template <typename ICHandler>
int GetPrototypeCheckCount(
    Isolate* isolate, Handle<Smi>* smi_handler, Handle<Map> receiver_map,
    Handle<JSReceiver> holder, MaybeObjectHandle data1,
    MaybeObjectHandle maybe_data2 = MaybeObjectHandle()) {
  DCHECK_NOT_NULL(smi_handler);
  return InitPrototypeChecksImpl<ICHandler, false>(isolate, Handle<ICHandler>(),
                                                   smi_handler, receiver_map,
                                                   holder, data1, maybe_data2);
}

template <typename ICHandler>
void InitPrototypeChecks(Isolate* isolate, Handle<ICHandler> handler,
                         Handle<Map> receiver_map, Handle<JSReceiver> holder,
                         MaybeObjectHandle data1,
                         MaybeObjectHandle maybe_data2 = MaybeObjectHandle()) {
  InitPrototypeChecksImpl<ICHandler, true>(
      isolate, handler, nullptr, receiver_map, holder, data1, maybe_data2);
}

}  // namespace

// static
Handle<Object> LoadHandler::LoadFromPrototype(Isolate* isolate,
                                              Handle<Map> receiver_map,
                                              Handle<JSReceiver> holder,
                                              Handle<Smi> smi_handler,
                                              MaybeObjectHandle maybe_data1,
                                              MaybeObjectHandle maybe_data2) {
  MaybeObjectHandle data1;
  if (maybe_data1.is_null()) {
    data1 = MaybeObjectHandle::Weak(holder);
  } else {
    data1 = maybe_data1;
  }

  int checks_count = GetPrototypeCheckCount<LoadHandler>(
      isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);

  int data_count = 1 + checks_count;
  Handle<LoadHandler> handler = isolate->factory()->NewLoadHandler(data_count);

  handler->set_smi_handler(*smi_handler);
  handler->set_validity_cell(*validity_cell);
  InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
                      maybe_data2);
  return handler;
}

// static
Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
                                          Handle<Map> receiver_map,
                                          const MaybeObjectHandle& holder,
                                          Handle<Smi> smi_handler) {
  Handle<JSReceiver> end;  // null handle, means full prototype chain lookup.
  MaybeObjectHandle data1 = holder;
  int checks_count = GetPrototypeCheckCount<LoadHandler>(
      isolate, &smi_handler, receiver_map, end, data1);

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  if (validity_cell->IsSmi()) {
    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;
  }

  int data_count = 1 + checks_count;
  Handle<LoadHandler> handler = isolate->factory()->NewLoadHandler(data_count);

  handler->set_smi_handler(*smi_handler);
  handler->set_validity_cell(*validity_cell);
  InitPrototypeChecks(isolate, handler, receiver_map, end, data1);
  return handler;
}

// static
KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject handler) {
  DisallowHeapAllocation no_gc;
  if (handler->IsSmi()) {
    int const raw_handler = handler.ToSmi().value();
    Kind const kind = KindBits::decode(raw_handler);
    if ((kind == kElement || kind == kIndexedString) &&
        AllowOutOfBoundsBits::decode(raw_handler)) {
      return LOAD_IGNORE_OUT_OF_BOUNDS;
    }
  }
  return STANDARD_LOAD;
}

// static
Handle<Object> StoreHandler::StoreElementTransition(
    Isolate* isolate, Handle<Map> receiver_map, Handle<Map> transition,
    KeyedAccessStoreMode store_mode) {
  Handle<Code> stub =
      CodeFactory::ElementsTransitionAndStore(isolate, store_mode).code();
  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(1);
  handler->set_smi_handler(*stub);
  handler->set_validity_cell(*validity_cell);
  handler->set_data1(HeapObjectReference::Weak(*transition));
  return handler;
}

MaybeObjectHandle StoreHandler::StoreTransition(Isolate* isolate,
                                                Handle<Map> transition_map) {
  bool is_dictionary_map = transition_map->is_dictionary_map();
#ifdef DEBUG
  if (!is_dictionary_map) {
    int descriptor = transition_map->LastAdded();
    Handle<DescriptorArray> descriptors(transition_map->instance_descriptors(),
                                        isolate);
    PropertyDetails details = descriptors->GetDetails(descriptor);
    if (descriptors->GetKey(descriptor).IsPrivate()) {
      DCHECK_EQ(DONT_ENUM, details.attributes());
    } else {
      DCHECK_EQ(NONE, details.attributes());
    }
    Representation representation = details.representation();
    DCHECK(!representation.IsNone());
  }
#endif
  // Declarative handlers don't support access checks.
  DCHECK(!transition_map->is_access_check_needed());

  // Get validity cell value if it is necessary for the handler.
  Handle<Object> validity_cell;
  if (is_dictionary_map || !transition_map->IsPrototypeValidityCellValid()) {
    validity_cell =
        Map::GetOrCreatePrototypeChainValidityCell(transition_map, isolate);
  }

  if (is_dictionary_map) {
    DCHECK(!transition_map->IsJSGlobalObjectMap());
    Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(0);
    // Store normal with enabled lookup on receiver.
    int config = KindBits::encode(kNormal) | LookupOnReceiverBits::encode(true);
    handler->set_smi_handler(Smi::FromInt(config));
    handler->set_validity_cell(*validity_cell);
    return MaybeObjectHandle(handler);

  } else {
    // Ensure the transition map contains a valid prototype validity cell.
    if (!validity_cell.is_null()) {
      transition_map->set_prototype_validity_cell(*validity_cell);
    }
    return MaybeObjectHandle::Weak(transition_map);
  }
}

// static
Handle<Object> StoreHandler::StoreThroughPrototype(
    Isolate* isolate, Handle<Map> receiver_map, Handle<JSReceiver> holder,
    Handle<Smi> smi_handler, MaybeObjectHandle maybe_data1,
    MaybeObjectHandle maybe_data2) {
  MaybeObjectHandle data1;
  if (maybe_data1.is_null()) {
    data1 = MaybeObjectHandle::Weak(holder);
  } else {
    data1 = maybe_data1;
  }

  int checks_count = GetPrototypeCheckCount<StoreHandler>(
      isolate, &smi_handler, receiver_map, holder, data1, maybe_data2);

  Handle<Object> validity_cell =
      Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
  DCHECK_IMPLIES(validity_cell->IsSmi(), checks_count == 0);

  int data_count = 1 + checks_count;
  Handle<StoreHandler> handler =
      isolate->factory()->NewStoreHandler(data_count);

  handler->set_smi_handler(*smi_handler);
  handler->set_validity_cell(*validity_cell);
  InitPrototypeChecks(isolate, handler, receiver_map, holder, data1,
                      maybe_data2);
  return handler;
}

// static
MaybeObjectHandle StoreHandler::StoreGlobal(Handle<PropertyCell> cell) {
  return MaybeObjectHandle::Weak(cell);
}

// static
Handle<Object> StoreHandler::StoreProxy(Isolate* isolate,
                                        Handle<Map> receiver_map,
                                        Handle<JSProxy> proxy,
                                        Handle<JSReceiver> receiver) {
  Handle<Smi> smi_handler = StoreProxy(isolate);
  if (receiver.is_identical_to(proxy)) return smi_handler;
  return StoreThroughPrototype(isolate, receiver_map, proxy, smi_handler,
                               MaybeObjectHandle::Weak(proxy));
}

}  // namespace internal
}  // namespace v8
