// 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_SRC_IC_ACCESSOR_ASSEMBLER_H_
#define V8_SRC_IC_ACCESSOR_ASSEMBLER_H_

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

namespace v8 {
namespace internal {

namespace compiler {
class CodeAssemblerState;
}

class ExitPoint;

class AccessorAssembler : public CodeStubAssembler {
 public:
  typedef compiler::Node Node;

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

  void GenerateLoadIC();
  void GenerateLoadIC_Noninlined();
  void GenerateLoadIC_Uninitialized();
  void GenerateLoadField();
  void GenerateLoadICTrampoline();
  void GenerateKeyedLoadIC();
  void GenerateKeyedLoadICTrampoline();
  void GenerateKeyedLoadIC_Megamorphic();
  void GenerateKeyedLoadIC_PolymorphicName();
  void GenerateStoreIC();
  void GenerateStoreICTrampoline();
  void GenerateStoreGlobalIC();
  void GenerateStoreGlobalICTrampoline();

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

  void GenerateKeyedStoreIC();
  void GenerateKeyedStoreICTrampoline();

  void TryProbeStubCache(StubCache* stub_cache, Node* receiver, Node* name,
                         Label* if_handler, Variable* 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(Node* 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) {}

    Node* context;
    Node* receiver;
    Node* name;
    Node* slot;
    Node* vector;
    Node* holder;
  };

  void LoadGlobalIC(TNode<FeedbackVector> 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 LoadICParameters* p, ExitPoint* exit_point);

  // Loads dataX field from the DataHandler object.
  Node* LoadHandlerDataField(Node* handler, int data_index);

 protected:
  struct StoreICParameters : public LoadICParameters {
    StoreICParameters(Node* context, Node* receiver, Node* name, Node* value,
                      Node* slot, Node* vector)
        : LoadICParameters(context, receiver, name, slot, vector),
          value(value) {}
    Node* value;
  };

  enum class ICMode { kNonGlobalIC, kGlobalIC };
  enum ElementSupport { kOnlyProperties, kSupportElements };
  void HandleStoreICHandlerCase(
      const StoreICParameters* p, Node* handler, Label* miss, ICMode ic_mode,
      ElementSupport support_elements = kOnlyProperties);
  void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);

  void BranchIfStrictMode(Node* vector, Node* slot, Label* if_strict);

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

 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,
                         Node* feedback, Variable* var_handler,
                         Label* if_handler, Label* miss, ExitPoint* exit_point);

  Node* LoadDescriptorValue(Node* map, Node* descriptor);

  void LoadIC_Uninitialized(const LoadICParameters* p);

  void KeyedLoadIC(const LoadICParameters* p);
  void KeyedLoadICGeneric(const LoadICParameters* p);
  void KeyedLoadICPolymorphicName(const LoadICParameters* p);
  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);

  // IC dispatcher behavior.

  // Checks monomorphic case. Returns {feedback} entry of the vector.
  Node* TryMonomorphicCase(Node* slot, Node* vector, Node* receiver_map,
                           Label* if_handler, Variable* var_handler,
                           Label* if_miss);
  void HandlePolymorphicCase(Node* receiver_map, Node* feedback,
                             Label* if_handler, Variable* var_handler,
                             Label* if_miss, int min_feedback_capacity);

  // LoadIC implementation.
  enum class OnNonExistent { kThrowReferenceError, kReturnUndefined };
  void HandleLoadICHandlerCase(
      const LoadICParameters* p, Node* handler, Label* miss,
      ExitPoint* exit_point, ICMode ic_mode = ICMode::kNonGlobalIC,
      OnNonExistent on_nonexistent = OnNonExistent::kReturnUndefined,
      ElementSupport support_elements = kOnlyProperties);

  void HandleLoadICSmiHandlerCase(const LoadICParameters* p, Node* holder,
                                  Node* smi_handler, Node* handler, Label* miss,
                                  ExitPoint* exit_point,
                                  OnNonExistent on_nonexistent,
                                  ElementSupport support_elements);

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

  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);

  // 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, Node* handler,
                                 Label* miss, ICMode ic_mode,
                                 ElementSupport support_elements);
  // If |transition| is nullptr then the normal field store is generated or
  // transitioning store otherwise.
  void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder,
                                   Node* value, Node* transition, Label* miss);
  // If |transition| is nullptr then the normal field store is generated or
  // transitioning store otherwise.
  void HandleStoreFieldAndReturn(Node* handler_word, Node* holder,
                                 Representation representation, Node* value,
                                 Node* transition, 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,
                          Node* instance_type, Node* index, Label* slow);

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

  // Low-level helpers.

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

  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* GetLanguageMode(Node* vector, Node* slot);

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

  // Extends properties backing store by JSObject::kFieldsAdded elements.
  void ExtendPropertiesBackingStore(Node* object, Node* handler_word);

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

  void EmitFastElementsBoundsCheck(Node* object, Node* elements,
                                   Node* intptr_index,
                                   Node* is_jsarray_condition, Label* miss);
  void EmitElementLoad(Node* object, Node* elements, Node* elements_kind,
                       Node* 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);
  void NameDictionaryNegativeLookup(Node* object, Node* name, Label* miss);

  // 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, Variable* 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:
  typedef compiler::Node Node;
  typedef compiler::CodeAssemblerLabel CodeAssemblerLabel;
  typedef compiler::CodeAssemblerVariable CodeAssemblerVariable;

 public:
  explicit ExitPoint(CodeStubAssembler* assembler)
      : ExitPoint(assembler, nullptr, nullptr) {}
  ExitPoint(CodeStubAssembler* assembler, CodeAssemblerLabel* out,
            CodeAssemblerVariable* var_result)
      : out_(out), var_result_(var_result), asm_(assembler) {
    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 {
      IndirectReturn(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 {
      IndirectReturn(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 {
      IndirectReturn(asm_->CallStub(descriptor, target, context, args...));
    }
  }

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

  bool IsDirect() const { return out_ == nullptr; }

 private:
  void IndirectReturn(Node* const result) {
    var_result_->Bind(result);
    asm_->Goto(out_);
  }

  CodeAssemblerLabel* const out_;
  CodeAssemblerVariable* const var_result_;
  CodeStubAssembler* const asm_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SRC_IC_ACCESSOR_ASSEMBLER_H_
