// 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/base/optional.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/compiler/code-assembler.h"

namespace v8 {
namespace internal {

namespace compiler {
class CodeAssemblerState;
}  // namespace compiler

class ExitPoint;

class V8_EXPORT_PRIVATE AccessorAssembler : public CodeStubAssembler {
 public:
  using Node = compiler::Node;

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

  void GenerateLoadIC();
  void GenerateLoadIC_Megamorphic();
  void GenerateLoadIC_Noninlined();
  void GenerateLoadIC_NoFeedback();
  void GenerateLoadGlobalIC_NoFeedback();
  void GenerateLoadICTrampoline();
  void GenerateLoadICTrampoline_Megamorphic();
  void GenerateLoadSuperIC();
  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,
                         TNode<Object> lookup_start_object, TNode<Name> name,
                         Label* if_handler, TVariable<MaybeObject>* var_handler,
                         Label* if_miss);

  TNode<IntPtrT> StubCachePrimaryOffsetForTesting(TNode<Name> name,
                                                  TNode<Map> map) {
    return StubCachePrimaryOffset(name, map);
  }
  TNode<IntPtrT> StubCacheSecondaryOffsetForTesting(TNode<Name> name,
                                                    TNode<IntPtrT> seed) {
    return StubCacheSecondaryOffset(name, seed);
  }

  struct LoadICParameters {
    LoadICParameters(
        TNode<Context> context, TNode<Object> receiver, TNode<Object> name,
        TNode<TaggedIndex> slot, TNode<HeapObject> vector,
        base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
        : context_(context),
          receiver_(receiver),
          name_(name),
          slot_(slot),
          vector_(vector),
          lookup_start_object_(lookup_start_object ? lookup_start_object.value()
                                                   : receiver) {}

    LoadICParameters(const LoadICParameters* p, TNode<Object> unique_name)
        : context_(p->context_),
          receiver_(p->receiver_),
          name_(unique_name),
          slot_(p->slot_),
          vector_(p->vector_),
          lookup_start_object_(p->lookup_start_object_) {}

    TNode<Context> context() const { return context_; }
    TNode<Object> receiver() const { return receiver_; }
    TNode<Object> name() const { return name_; }
    TNode<TaggedIndex> slot() const { return slot_; }
    TNode<HeapObject> vector() const { return vector_; }
    TNode<Object> lookup_start_object() const {
      return lookup_start_object_.value();
    }

    // Usable in cases where the receiver and the lookup start object are
    // expected to be the same, i.e., when "receiver != lookup_start_object"
    // case is not supported or not expected by the surrounding code.
    TNode<Object> receiver_and_lookup_start_object() const {
      DCHECK_EQ(receiver_, lookup_start_object_);
      return receiver_;
    }

   private:
    TNode<Context> context_;
    TNode<Object> receiver_;
    TNode<Object> name_;
    TNode<TaggedIndex> slot_;
    TNode<HeapObject> vector_;
    base::Optional<TNode<Object>> lookup_start_object_;
  };

  struct LazyLoadICParameters {
    LazyLoadICParameters(
        LazyNode<Context> context, TNode<Object> receiver,
        LazyNode<Object> name, LazyNode<TaggedIndex> slot,
        TNode<HeapObject> vector,
        base::Optional<TNode<Object>> lookup_start_object = base::nullopt)
        : context_(context),
          receiver_(receiver),
          name_(name),
          slot_(slot),
          vector_(vector),
          lookup_start_object_(lookup_start_object ? lookup_start_object.value()
                                                   : receiver) {}

    explicit LazyLoadICParameters(const LoadICParameters* p)
        : receiver_(p->receiver()),
          vector_(p->vector()),
          lookup_start_object_(p->lookup_start_object()) {
      slot_ = [=] { return p->slot(); };
      context_ = [=] { return p->context(); };
      name_ = [=] { return p->name(); };
    }

    TNode<Context> context() const { return context_(); }
    TNode<Object> receiver() const { return receiver_; }
    TNode<Object> name() const { return name_(); }
    TNode<TaggedIndex> slot() const { return slot_(); }
    TNode<HeapObject> vector() const { return vector_; }
    TNode<Object> lookup_start_object() const { return lookup_start_object_; }

    // Usable in cases where the receiver and the lookup start object are
    // expected to be the same, i.e., when "receiver != lookup_start_object"
    // case is not supported or not expected by the surrounding code.
    TNode<Object> receiver_and_lookup_start_object() const {
      DCHECK_EQ(receiver_, lookup_start_object_);
      return receiver_;
    }

   private:
    LazyNode<Context> context_;
    TNode<Object> receiver_;
    LazyNode<Object> name_;
    LazyNode<TaggedIndex> slot_;
    TNode<HeapObject> vector_;
    TNode<Object> lookup_start_object_;
  };

  void LoadGlobalIC(TNode<HeapObject> maybe_feedback_vector,
                    const LazyNode<TaggedIndex>& lazy_slot,
                    const LazyNode<Context>& lazy_context,
                    const LazyNode<Name>& lazy_name, TypeofMode typeof_mode,
                    ExitPoint* exit_point);

  // 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(TNode<DataHandler> handler,
                                          int data_index);

 protected:
  struct StoreICParameters {
    StoreICParameters(TNode<Context> context,
                      base::Optional<TNode<Object>> receiver,
                      TNode<Object> name, TNode<Object> value,
                      TNode<TaggedIndex> slot, TNode<HeapObject> vector)
        : context_(context),
          receiver_(receiver),
          name_(name),
          value_(value),
          slot_(slot),
          vector_(vector) {}

    TNode<Context> context() const { return context_; }
    TNode<Object> receiver() const { return receiver_.value(); }
    TNode<Object> name() const { return name_; }
    TNode<Object> value() const { return value_; }
    TNode<TaggedIndex> slot() const { return slot_; }
    TNode<HeapObject> vector() const { return vector_; }

    TNode<Object> lookup_start_object() const { return receiver(); }

    bool receiver_is_null() const { return !receiver_.has_value(); }

   private:
    TNode<Context> context_;
    base::Optional<TNode<Object>> receiver_;
    TNode<Object> name_;
    TNode<Object> value_;
    TNode<TaggedIndex> slot_;
    TNode<HeapObject> vector_;
  };

  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(TNode<Uint32T> details, Label* writable,
                          Label* readonly);

  void InvalidateValidityCellIfPrototype(
      TNode<Map> map, base::Optional<TNode<Uint32T>> bitfield3 = base::nullopt);

  void OverwriteExistingFastDataProperty(TNode<HeapObject> object,
                                         TNode<Map> object_map,
                                         TNode<DescriptorArray> descriptors,
                                         TNode<IntPtrT> descriptor_name_index,
                                         TNode<Uint32T> details,
                                         TNode<Object> value, Label* slow,
                                         bool do_transitioning_store);

  void CheckFieldType(TNode<DescriptorArray> descriptors,
                      TNode<IntPtrT> name_index, TNode<Word32T> representation,
                      TNode<Object> 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);

  // Can be used in the receiver != lookup_start_object case.
  void LoadIC_Noninlined(const LoadICParameters* p,
                         TNode<Map> lookup_start_object_map,
                         TNode<HeapObject> feedback,
                         TVariable<MaybeObject>* var_handler, Label* if_handler,
                         Label* miss, ExitPoint* exit_point);

  void LoadSuperIC(const LoadICParameters* p);

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

  void LoadIC_NoFeedback(const LoadICParameters* p, TNode<Smi> smi_typeof_mode);
  void LoadSuperIC_NoFeedback(const LoadICParameters* p);
  void LoadGlobalIC_NoFeedback(TNode<Context> context, TNode<Object> name,
                               TNode<Smi> smi_typeof_mode);

  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(TNode<PropertyCell> property_cell,
                                      TNode<Object> 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(TNode<TaggedIndex> slot,
                                        TNode<FeedbackVector> vector,
                                        TNode<Map> lookup_start_object_map,
                                        Label* if_handler,
                                        TVariable<MaybeObject>* var_handler,
                                        Label* if_miss);
  void HandlePolymorphicCase(TNode<Map> lookup_start_object_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,
                                  TNode<Object> holder, TNode<Smi> smi_handler,
                                  TNode<Object> handler, Label* miss,
                                  ExitPoint* exit_point, ICMode ic_mode,
                                  OnNonExistent on_nonexistent,
                                  ElementSupport support_elements,
                                  LoadAccessMode access_mode);

  void HandleLoadICProtoHandler(const LazyLoadICParameters* p,
                                TNode<DataHandler> handler,
                                TVariable<Object>* var_holder,
                                TVariable<Object>* 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(TNode<JSObject> holder, TNode<WordT> handler_word,
                       TVariable<Float64T>* var_double_value,
                       Label* rebox_double, Label* miss, ExitPoint* exit_point);

  void EmitAccessCheck(TNode<Context> expected_native_context,
                       TNode<Context> context, TNode<Object> receiver,
                       Label* can_access, Label* miss);

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

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

  // LoadGlobalIC implementation.

  void LoadGlobalIC_TryPropertyCellCase(TNode<FeedbackVector> vector,
                                        TNode<TaggedIndex> slot,
                                        const LazyNode<Context>& lazy_context,
                                        ExitPoint* exit_point,
                                        Label* try_handler, Label* miss);

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

  // This is a copy of ScriptContextTable::Lookup. They should be kept in sync.
  void ScriptContextTableLookup(TNode<Name> name,
                                TNode<NativeContext> native_context,
                                Label* found_hole, Label* not_found);

  // StoreIC implementation.

  void HandleStoreICProtoHandler(const StoreICParameters* p,
                                 TNode<StoreHandler> handler, Label* miss,
                                 ICMode ic_mode,
                                 ElementSupport support_elements);
  void HandleStoreICSmiHandlerCase(TNode<Word32T> handler_word,
                                   TNode<JSObject> holder, TNode<Object> value,
                                   Label* miss);
  void HandleStoreFieldAndReturn(TNode<Word32T> handler_word,
                                 TNode<JSObject> holder, TNode<Object> value,
                                 base::Optional<TNode<Float64T>> double_value,
                                 Representation representation, Label* miss);

  void CheckPrototypeValidityCell(TNode<Object> maybe_validity_cell,
                                  Label* miss);
  void HandleStoreICNativeDataProperty(const StoreICParameters* p,
                                       TNode<HeapObject> holder,
                                       TNode<Word32T> handler_word);

  void HandleStoreToProxy(const StoreICParameters* p, TNode<JSProxy> proxy,
                          Label* miss, ElementSupport support_elements);

  void HandleStoreAccessor(const StoreICParameters* p, TNode<HeapObject> holder,
                           TNode<Word32T> handler_word);

  // KeyedLoadIC_Generic implementation.

  void GenericElementLoad(TNode<HeapObject> lookup_start_object,
                          TNode<Map> lookup_start_object_map,
                          TNode<Int32T> lookup_start_object_instance_type,
                          TNode<IntPtrT> index, Label* slow);

  enum UseStubCache { kUseStubCache, kDontUseStubCache };
  void GenericPropertyLoad(TNode<HeapObject> lookup_start_object,
                           TNode<Map> lookup_start_object_map,
                           TNode<Int32T> lookup_start_object_instance_type,
                           const LoadICParameters* p, Label* slow,
                           UseStubCache use_stub_cache = kUseStubCache);

  // Low-level helpers.

  using OnCodeHandler = std::function<void(TNode<Code> code_handler)>;
  using OnFoundOnLookupStartObject = std::function<void(
      TNode<NameDictionary> properties, TNode<IntPtrT> name_index)>;

  template <typename ICHandler, typename ICParameters>
  TNode<Object> HandleProtoHandler(
      const ICParameters* p, TNode<DataHandler> handler,
      const OnCodeHandler& on_code_handler,
      const OnFoundOnLookupStartObject& on_found_on_lookup_start_object,
      Label* miss, ICMode ic_mode);

  void CheckHeapObjectTypeMatchesDescriptor(TNode<Word32T> handler_word,
                                            TNode<JSObject> holder,
                                            TNode<Object> value,
                                            Label* bailout);
  // Double fields store double values in a mutable box, where stores are
  // writes into this box rather than HeapNumber assignment.
  void CheckDescriptorConsidersNumbersMutable(TNode<Word32T> handler_word,
                                              TNode<JSObject> holder,
                                              Label* bailout);

  // Extends properties backing store by JSObject::kFieldsAdded elements,
  // returns updated properties backing store.
  TNode<PropertyArray> ExtendPropertiesBackingStore(TNode<HeapObject> object,
                                                    TNode<IntPtrT> index);

  void EmitFastElementsBoundsCheck(TNode<JSObject> object,
                                   TNode<FixedArrayBase> elements,
                                   TNode<IntPtrT> intptr_index,
                                   TNode<BoolT> is_jsarray_condition,
                                   Label* miss);
  void EmitElementLoad(TNode<HeapObject> object, TNode<Word32T> elements_kind,
                       TNode<IntPtrT> key, TNode<BoolT> is_jsarray_condition,
                       Label* if_hole, Label* rebox_double,
                       TVariable<Float64T>* var_double_value,
                       Label* unimplemented_elements_kind, Label* out_of_bounds,
                       Label* miss, ExitPoint* exit_point,
                       LoadAccessMode access_mode = LoadAccessMode::kLoad);
  TNode<BoolT> IsPropertyDetailsConst(TNode<Uint32T> 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;

  TNode<IntPtrT> StubCachePrimaryOffset(TNode<Name> name, TNode<Map> map);
  TNode<IntPtrT> StubCacheSecondaryOffset(TNode<Name> name,
                                          TNode<IntPtrT> seed);

  void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
                              TNode<IntPtrT> entry_offset, TNode<Object> name,
                              TNode<Map> map, Label* if_handler,
                              TVariable<MaybeObject>* var_handler,
                              Label* if_miss);

  void BranchIfPrototypesHaveNoElements(TNode<Map> receiver_map,
                                        Label* definitely_no_elements,
                                        Label* possibly_elements);
};

// 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 CodeAssemblerLabel = compiler::CodeAssemblerLabel;

 public:
  using IndirectReturnHandler = std::function<void(TNode<Object> 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,
            compiler::CodeAssembler::TVariable<Object>* var_result)
      : ExitPoint(assembler, [=](TNode<Object> result) {
          *var_result = result;
          assembler->Goto(out);
        }) {
    DCHECK_EQ(out != nullptr, var_result != nullptr);
  }

  template <class... TArgs>
  void ReturnCallRuntime(Runtime::FunctionId function, TNode<Context> 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, TNode<Context> 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,
                      TNode<Code> target, TNode<Context> context,
                      TArgs... args) {
    if (IsDirect()) {
      asm_->TailCallStub(descriptor, target, context, args...);
    } else {
      indirect_return_handler_(
          asm_->CallStub(descriptor, target, context, args...));
    }
  }

  void Return(const TNode<Object> 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_
