// Copyright 2016 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_IC_ACCESSOR_ASSEMBLER_H_
#define V8_IC_ACCESSOR_ASSEMBLER_H_

#include "src/codegen/code-stub-assembler.h"

namespace v8 {
namespace internal {

namespace compiler {
class CodeAssemblerState;
}

class ExitPoint;

class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
 public:
  using Node = compiler::Node;
  template <class T>
  using TNode = compiler::TNode<T>;
  template <class T>
  using SloppyTNode = compiler::SloppyTNode<T>;

  explicit AccessorAssembler(compiler::CodeAssemblerState* state)
      : CodeStubAssembler(state) {}

  void GenerateLoadIC();
  void GenerateLoadIC_Megamorphic();
  void GenerateLoadIC_Noninlined();
  void GenerateLoadIC_Uninitialized();
  void GenerateLoadICTrampoline();
  void GenerateLoadICTrampoline_Megamorphic();
  void GenerateKeyedLoadIC();
  void GenerateKeyedLoadIC_Megamorphic();
  void GenerateKeyedLoadIC_PolymorphicName();
  void GenerateKeyedLoadICTrampoline();
  void GenerateKeyedLoadICTrampoline_Megamorphic();
  void GenerateStoreIC();
  void GenerateStoreICTrampoline();
  void GenerateStoreGlobalIC();
  void GenerateStoreGlobalICTrampoline();
  void GenerateCloneObjectIC();
  void GenerateCloneObjectIC_Slow();
  void GenerateKeyedHasIC();
  void GenerateKeyedHasIC_Megamorphic();
  void GenerateKeyedHasIC_PolymorphicName();

  void GenerateLoadGlobalIC(TypeofMode typeof_mode);
  void GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode);

  void GenerateKeyedStoreIC();
  void GenerateKeyedStoreICTrampoline();

  void GenerateStoreInArrayLiteralIC();

  void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
                         Label* if_handler, TVariable<MaybeObject>* var_handler,
                         Label* if_miss);

  Node* StubCachePrimaryOffsetForTesting(Node* name, Node* map) {
    return StubCachePrimaryOffset(name, map);
  }
  Node* StubCacheSecondaryOffsetForTesting(Node* name, Node* map) {
    return StubCacheSecondaryOffset(name, map);
  }

  struct LoadICParameters {
    LoadICParameters(TNode<Context> context, Node* receiver, Node* name,
                     Node* slot, Node* vector, Node* holder = nullptr)
        : context_(context),
          receiver_(receiver),
          name_(name),
          slot_(slot),
          vector_(vector),
          holder_(holder ? holder : receiver) {}

    LoadICParameters(const LoadICParameters* p, Node* unique_name)
        : context_(p->context_),
          receiver_(p->receiver_),
          name_(unique_name),
          slot_(p->slot_),
          vector_(p->vector_),
          holder_(p->holder_) {}

    TNode<Context> context() const { return context_; }
    Node* receiver() const { return receiver_; }
    Node* name() const { return name_; }
    Node* slot() const { return slot_; }
    Node* vector() const { return vector_; }
    Node* holder() const { return holder_; }

   private:
    TNode<Context> context_;
    Node* receiver_;
    Node* name_;
    Node* slot_;
    Node* vector_;
    Node* holder_;
  };

  struct LazyLoadICParameters {
    LazyLoadICParameters(LazyNode<Context> context, Node* receiver,
                         LazyNode<Object> name, Node* slot, Node* vector,
                         Node* holder = nullptr)
        : context_(context),
          receiver_(receiver),
          name_(name),
          slot_(slot),
          vector_(vector),
          holder_(holder ? holder : receiver) {}

    explicit LazyLoadICParameters(const LoadICParameters* p)
        : receiver_(p->receiver()),
          slot_(p->slot()),
          vector_(p->vector()),
          holder_(p->holder()) {
      TNode<Context> p_context = p->context();
      context_ = [=] { return p_context; };
      TNode<Object> p_name = TNode<Object>::UncheckedCast(p->name());
      name_ = [=] { return p_name; };
    }

    TNode<Context> context() const { return context_(); }
    Node* receiver() const { return receiver_; }
    Node* name() const { return name_(); }
    Node* slot() const { return slot_; }
    Node* vector() const { return vector_; }
    Node* holder() const { return holder_; }

   private:
    LazyNode<Context> context_;
    Node* receiver_;
    LazyNode<Object> name_;
    Node* slot_;
    Node* vector_;
    Node* holder_;
  };

  void LoadGlobalIC(Node* vector, Node* slot,
                    const LazyNode<Context>& lazy_context,
                    const LazyNode<Name>& lazy_name, TypeofMode typeof_mode,
                    ExitPoint* exit_point,
                    ParameterMode slot_mode = SMI_PARAMETERS);

  // Specialized LoadIC for inlined bytecode handler, hand-tuned to omit frame
  // construction on common paths.
  void LoadIC_BytecodeHandler(const LazyLoadICParameters* p,
                              ExitPoint* exit_point);

  // Loads dataX field from the DataHandler object.
  TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
                                          int data_index);

 protected:
  struct StoreICParameters : public LoadICParameters {
    StoreICParameters(TNode<Context> context, Node* receiver, Node* name,
                      SloppyTNode<Object> value, Node* slot, Node* vector)
        : LoadICParameters(context, receiver, name, slot, vector),
          value_(value) {}

    SloppyTNode<Object> value() const { return value_; }

   private:
    SloppyTNode<Object> value_;
  };

  enum class LoadAccessMode { kLoad, kHas };
  enum class ICMode { kNonGlobalIC, kGlobalIC };
  enum ElementSupport { kOnlyProperties, kSupportElements };
  void HandleStoreICHandlerCase(
      const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
      ICMode ic_mode, ElementSupport support_elements = kOnlyProperties);
  enum StoreTransitionMapFlags {
    kCheckPrototypeValidity = 1 << 0,
    kValidateTransitionHandler = 1 << 1,
    kStoreTransitionMapFlagsMask =
        kCheckPrototypeValidity | kValidateTransitionHandler,
  };
  void HandleStoreICTransitionMapHandlerCase(const StoreICParameters* p,
                                             TNode<Map> transition_map,
                                             Label* miss,
                                             StoreTransitionMapFlags flags);

  void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);

  void InvalidateValidityCellIfPrototype(Node* map, Node* bitfield3 = nullptr);

  void OverwriteExistingFastDataProperty(Node* object, Node* object_map,
                                         Node* descriptors,
                                         Node* descriptor_name_index,
                                         Node* details, Node* value,
                                         Label* slow,
                                         bool do_transitioning_store);

  void CheckFieldType(TNode<DescriptorArray> descriptors, Node* name_index,
                      Node* representation, Node* value, Label* bailout);

 private:
  // Stub generation entry points.

  // LoadIC contains the full LoadIC logic, while LoadIC_Noninlined contains
  // logic not inlined into Ignition bytecode handlers.
  void LoadIC(const LoadICParameters* p);
  void LoadIC_Noninlined(const LoadICParameters* p, Node* receiver_map,
                         TNode<HeapObject> feedback,
                         TVariable<MaybeObject>* var_handler, Label* if_handler,
                         Label* miss, ExitPoint* exit_point);

  TNode<Object> LoadDescriptorValue(TNode<Map> map,
                                    TNode<IntPtrT> descriptor_entry);
  TNode<MaybeObject> LoadDescriptorValueOrFieldType(
      TNode<Map> map, TNode<IntPtrT> descriptor_entry);

  void LoadIC_Uninitialized(const LoadICParameters* p);

  void KeyedLoadIC(const LoadICParameters* p, LoadAccessMode access_mode);
  void KeyedLoadICGeneric(const LoadICParameters* p);
  void KeyedLoadICPolymorphicName(const LoadICParameters* p,
                                  LoadAccessMode access_mode);
  void StoreIC(const StoreICParameters* p);
  void StoreGlobalIC(const StoreICParameters* p);
  void StoreGlobalIC_PropertyCellCase(Node* property_cell, Node* value,
                                      ExitPoint* exit_point, Label* miss);
  void KeyedStoreIC(const StoreICParameters* p);
  void StoreInArrayLiteralIC(const StoreICParameters* p);

  // IC dispatcher behavior.

  // Checks monomorphic case. Returns {feedback} entry of the vector.
  TNode<MaybeObject> TryMonomorphicCase(Node* slot, Node* vector,
                                        Node* receiver_map, Label* if_handler,
                                        TVariable<MaybeObject>* var_handler,
                                        Label* if_miss);
  void HandlePolymorphicCase(Node* receiver_map, TNode<WeakFixedArray> feedback,
                             Label* if_handler,
                             TVariable<MaybeObject>* var_handler,
                             Label* if_miss);

  // LoadIC implementation.
  void HandleLoadICHandlerCase(
      const LazyLoadICParameters* p, TNode<Object> handler, Label* miss,
      ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
      OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
      ElementSupport support_elements = kOnlyProperties,
      LoadAccessMode access_mode = LoadAccessMode::kLoad);

  void HandleLoadICSmiHandlerCase(const LazyLoadICParameters* p, Node* holder,
                                  SloppyTNode<Smi> smi_handler,
                                  SloppyTNode<Object> handler, Label* miss,
                                  ExitPoint* exit_point,
                                  OnNonExistent on_nonexistent,
                                  ElementSupport support_elements,
                                  LoadAccessMode access_mode);

  void HandleLoadICProtoHandler(const LazyLoadICParameters* p, Node* handler,
                                Variable* var_holder, Variable* var_smi_handler,
                                Label* if_smi_handler, Label* miss,
                                ExitPoint* exit_point, ICMode ic_mode,
                                LoadAccessMode access_mode);

  void HandleLoadCallbackProperty(const LazyLoadICParameters* p,
                                  TNode<JSObject> holder,
                                  TNode<WordT> handler_word,
                                  ExitPoint* exit_point);

  void HandleLoadAccessor(const LazyLoadICParameters* p,
                          TNode<CallHandlerInfo> call_handler_info,
                          TNode<WordT> handler_word, TNode<DataHandler> handler,
                          TNode<IntPtrT> handler_kind, ExitPoint* exit_point);

  void HandleLoadField(Node* holder, Node* handler_word,
                       Variable* var_double_value, Label* rebox_double,
                       ExitPoint* exit_point);

  void EmitAccessCheck(Node* expected_native_context, Node* context,
                       Node* receiver, Label* can_access, Label* miss);

  void HandleLoadICSmiHandlerLoadNamedCase(
      const LazyLoadICParameters* p, Node* holder, TNode<IntPtrT> handler_kind,
      TNode<WordT> handler_word, Label* rebox_double,
      Variable* var_double_value, SloppyTNode<Object> handler, Label* miss,
      ExitPoint* exit_point, OnNonExistent on_nonexistent,
      ElementSupport support_elements);

  void HandleLoadICSmiHandlerHasNamedCase(const LazyLoadICParameters* p,
                                          Node* holder,
                                          TNode<IntPtrT> handler_kind,
                                          Label* miss, ExitPoint* exit_point);

  // LoadGlobalIC implementation.

  void LoadGlobalIC_TryPropertyCellCase(
      TNode<FeedbackVector> vector, Node* slot,
      const LazyNode<Context>& lazy_context, ExitPoint* exit_point,
      Label* try_handler, Label* miss,
      ParameterMode slot_mode = SMI_PARAMETERS);

  void LoadGlobalIC_TryHandlerCase(TNode<FeedbackVector> vector, Node* slot,
                                   const LazyNode<Context>& lazy_context,
                                   const LazyNode<Name>& lazy_name,
                                   TypeofMode typeof_mode,
                                   ExitPoint* exit_point, Label* miss,
                                   ParameterMode slot_mode);

  // StoreIC implementation.

  void HandleStoreICProtoHandler(const StoreICParameters* p,
                                 TNode<StoreHandler> handler, Label* miss,
                                 ICMode ic_mode,
                                 ElementSupport support_elements);
  void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
                                   Node* value, Label* miss);
  void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
                                 Representation representation, Node* value,
                                 Label* miss);

  void CheckPrototypeValidityCell(Node* maybe_validity_cell, Label* miss);
  void HandleStoreICNativeDataProperty(const StoreICParameters* p, Node* holder,
                                       Node* handler_word);

  void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss,
                          ElementSupport support_elements);

  void HandleStoreAccessor(const StoreICParameters* p, Node* holder,
                           Node* handler_word);

  // KeyedLoadIC_Generic implementation.

  void GenericElementLoad(Node* receiver, Node* receiver_map,
                          SloppyTNode<Int32T> instance_type, Node* index,
                          Label* slow);

  enum UseStubCache { kUseStubCache, kDontUseStubCache };
  void GenericPropertyLoad(Node* receiver, Node* receiver_map,
                           SloppyTNode<Int32T> instance_type,
                           const LoadICParameters* p, Label* slow,
                           UseStubCache use_stub_cache = kUseStubCache);

  // Low-level helpers.

  using OnCodeHandler = std::function<void(Node* code_handler)>;
  using OnFoundOnReceiver =
      std::function<void(Node* properties, Node* name_index)>;

  template <typename ICHandler, typename ICParameters>
  Node* HandleProtoHandler(const ICParameters* p, Node* handler,
                           const OnCodeHandler& on_code_handler,
                           const OnFoundOnReceiver& on_found_on_receiver,
                           Label* miss, ICMode ic_mode);

  Node* PrepareValueForStore(Node* handler_word, Node* holder,
                             Representation representation, Node* value,
                             Label* bailout);

  // Extends properties backing store by JSObject::kFieldsAdded elements,
  // returns updated properties backing store.
  Node* ExtendPropertiesBackingStore(Node* object, Node* index);

  void StoreNamedField(Node* handler_word, Node* object, bool is_inobject,
                       Representation representation, Node* value,
                       Label* bailout);

  void EmitFastElementsBoundsCheck(Node* object, Node* elements,
                                   Node* intptr_index,
                                   Node* is_jsarray_condition, Label* miss);
  void EmitElementLoad(Node* object, Node* elements_kind,
                       SloppyTNode<IntPtrT> key, Node* is_jsarray_condition,
                       Label* if_hole, Label* rebox_double,
                       Variable* var_double_value,
                       Label* unimplemented_elements_kind, Label* out_of_bounds,
                       Label* miss, ExitPoint* exit_point,
                       LoadAccessMode access_mode = LoadAccessMode::kLoad);
  void NameDictionaryNegativeLookup(Node* object, SloppyTNode<Name> name,
                                    Label* miss);
  TNode<BoolT> IsPropertyDetailsConst(Node* details);

  // Stub cache access helpers.

  // This enum is used here as a replacement for StubCache::Table to avoid
  // including stub cache header.
  enum StubCacheTable : int;

  Node* StubCachePrimaryOffset(Node* name, Node* map);
  Node* StubCacheSecondaryOffset(Node* name, Node* seed);

  void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
                              Node* entry_offset, Node* name, Node* map,
                              Label* if_handler,
                              TVariable<MaybeObject>* var_handler,
                              Label* if_miss);
};

// Abstraction over direct and indirect exit points. Direct exits correspond to
// tailcalls and Return, while indirect exits store the result in a variable
// and then jump to an exit label.
class ExitPoint {
 private:
  using Node = compiler::Node;
  using CodeAssemblerLabel = compiler::CodeAssemblerLabel;
  using CodeAssemblerVariable = compiler::CodeAssemblerVariable;

 public:
  using IndirectReturnHandler = std::function<void(Node* result)>;

  explicit ExitPoint(CodeStubAssembler* assembler)
      : ExitPoint(assembler, nullptr) {}

  ExitPoint(CodeStubAssembler* assembler,
            const IndirectReturnHandler& indirect_return_handler)
      : asm_(assembler), indirect_return_handler_(indirect_return_handler) {}

  ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
            CodeAssemblerVariable* var_result)
      : ExitPoint(assembler, [=](Node* result) {
          var_result->Bind(result);
          assembler->Goto(out);
        }) {
    DCHECK_EQ(out != nullptr, var_result != nullptr);
  }

  template <class... TArgs>
  void ReturnCallRuntime(Runtime::FunctionId function, Node* context,
                         TArgs... args) {
    if (IsDirect()) {
      asm_->TailCallRuntime(function, context, args...);
    } else {
      indirect_return_handler_(asm_->CallRuntime(function, context, args...));
    }
  }

  template <class... TArgs>
  void ReturnCallStub(Callable const& callable, Node* context, TArgs... args) {
    if (IsDirect()) {
      asm_->TailCallStub(callable, context, args...);
    } else {
      indirect_return_handler_(asm_->CallStub(callable, context, args...));
    }
  }

  template <class... TArgs>
  void ReturnCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
                      Node* context, TArgs... args) {
    if (IsDirect()) {
      asm_->TailCallStub(descriptor, target, context, args...);
    } else {
      indirect_return_handler_(
          asm_->CallStub(descriptor, target, context, args...));
    }
  }

  void Return(Node* const result) {
    if (IsDirect()) {
      asm_->Return(result);
    } else {
      indirect_return_handler_(result);
    }
  }

  bool IsDirect() const { return !indirect_return_handler_; }

 private:
  CodeStubAssembler* const asm_;
  IndirectReturnHandler indirect_return_handler_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_IC_ACCESSOR_ASSEMBLER_H_
