// Copyright 2015 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_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
#define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_

#include "src/base/flags.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-heap-broker.h"
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/objects/map.h"

namespace v8 {
namespace internal {

// Forward declarations.
class Factory;
class JSGlobalObject;
class JSGlobalProxy;
class StringConstantBase;

namespace compiler {

// Forward declarations.
enum class AccessMode;
class CommonOperatorBuilder;
class CompilationDependencies;
class ElementAccessInfo;
class JSGraph;
class JSHeapBroker;
class JSOperatorBuilder;
class MachineOperatorBuilder;
class PropertyAccessInfo;
class SimplifiedOperatorBuilder;
class TypeCache;

// Specializes a given JSGraph to a given native context, potentially constant
// folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal}
// nodes.  And also specializes {LoadNamed} and {StoreNamed} nodes according
// to type feedback (if available).
class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
    : public AdvancedReducer {
 public:
  // Flags that control the mode of operation.
  enum Flag {
    kNoFlags = 0u,
    kBailoutOnUninitialized = 1u << 0,
  };
  using Flags = base::Flags<Flag>;

  JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
                                JSHeapBroker* broker, Flags flags,
                                CompilationDependencies* dependencies,
                                Zone* zone, Zone* shared_zone);
  JSNativeContextSpecialization(const JSNativeContextSpecialization&) = delete;
  JSNativeContextSpecialization& operator=(
      const JSNativeContextSpecialization&) = delete;

  const char* reducer_name() const override {
    return "JSNativeContextSpecialization";
  }

  Reduction Reduce(Node* node) final;

  // Utility for folding string constant concatenation.
  // Supports JSAdd nodes and nodes typed as string or number.
  // Public for the sake of unit testing.
  static base::Optional<size_t> GetMaxStringLength(JSHeapBroker* broker,
                                                   Node* node);

 private:
  Reduction ReduceJSAdd(Node* node);
  Reduction ReduceJSAsyncFunctionEnter(Node* node);
  Reduction ReduceJSAsyncFunctionReject(Node* node);
  Reduction ReduceJSAsyncFunctionResolve(Node* node);
  Reduction ReduceJSGetSuperConstructor(Node* node);
  Reduction ReduceJSInstanceOf(Node* node);
  Reduction ReduceJSHasInPrototypeChain(Node* node);
  Reduction ReduceJSOrdinaryHasInstance(Node* node);
  Reduction ReduceJSPromiseResolve(Node* node);
  Reduction ReduceJSResolvePromise(Node* node);
  Reduction ReduceJSLoadGlobal(Node* node);
  Reduction ReduceJSStoreGlobal(Node* node);
  Reduction ReduceJSLoadNamed(Node* node);
  Reduction ReduceJSLoadNamedFromSuper(Node* node);
  Reduction ReduceJSGetIterator(Node* node);
  Reduction ReduceJSStoreNamed(Node* node);
  Reduction ReduceJSHasProperty(Node* node);
  Reduction ReduceJSLoadProperty(Node* node);
  Reduction ReduceJSStoreProperty(Node* node);
  Reduction ReduceJSStoreNamedOwn(Node* node);
  Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
  Reduction ReduceJSStoreInArrayLiteral(Node* node);
  Reduction ReduceJSToObject(Node* node);

  Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
                                ElementAccessFeedback const& feedback);
  // In the case of non-keyed (named) accesses, pass the name as {static_name}
  // and use {nullptr} for {key} (load/store modes are irrelevant).
  Reduction ReducePropertyAccess(Node* node, Node* key,
                                 base::Optional<NameRef> static_name,
                                 Node* value, FeedbackSource const& source,
                                 AccessMode access_mode);
  Reduction ReduceNamedAccess(Node* node, Node* value,
                              NamedAccessFeedback const& feedback,
                              AccessMode access_mode, Node* key = nullptr);
  Reduction ReduceMinimorphicPropertyAccess(
      Node* node, Node* value,
      MinimorphicLoadPropertyAccessFeedback const& feedback,
      FeedbackSource const& source);
  Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object,
                               Node* receiver, Node* value, NameRef const& name,
                               AccessMode access_mode, Node* key = nullptr,
                               Node* effect = nullptr);
  Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object,
                               Node* receiver, Node* value, NameRef const& name,
                               AccessMode access_mode, Node* key,
                               PropertyCellRef const& property_cell,
                               Node* effect = nullptr);
  Reduction ReduceElementLoadFromHeapConstant(Node* node, Node* key,
                                              AccessMode access_mode,
                                              KeyedAccessLoadMode load_mode);
  Reduction ReduceElementAccessOnString(Node* node, Node* index, Node* value,
                                        KeyedAccessMode const& keyed_mode);

  Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
  Reduction ReduceJSToString(Node* node);

  Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);

  const StringConstantBase* CreateDelayedStringConstant(Node* node);

  // A triple of nodes that represents a continuation.
  class ValueEffectControl final {
   public:
    ValueEffectControl()
        : value_(nullptr), effect_(nullptr), control_(nullptr) {}
    ValueEffectControl(Node* value, Node* effect, Node* control)
        : value_(value), effect_(effect), control_(control) {}

    Node* value() const { return value_; }
    Node* effect() const { return effect_; }
    Node* control() const { return control_; }

   private:
    Node* value_;
    Node* effect_;
    Node* control_;
  };

  // Construct the appropriate subgraph for property access.
  ValueEffectControl BuildPropertyAccess(
      Node* lookup_start_object, Node* receiver, Node* value, Node* context,
      Node* frame_state, Node* effect, Node* control, NameRef const& name,
      ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info,
      AccessMode access_mode);
  ValueEffectControl BuildPropertyLoad(Node* lookup_start_object,
                                       Node* receiver, Node* context,
                                       Node* frame_state, Node* effect,
                                       Node* control, NameRef const& name,
                                       ZoneVector<Node*>* if_exceptions,
                                       PropertyAccessInfo const& access_info);

  ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
                                        Node* context, Node* frame_state,
                                        Node* effect, Node* control,
                                        NameRef const& name,
                                        ZoneVector<Node*>* if_exceptions,
                                        PropertyAccessInfo const& access_info,
                                        AccessMode access_mode);

  ValueEffectControl BuildPropertyTest(Node* effect, Node* control,
                                       PropertyAccessInfo const& access_info);

  // Helpers for accessor inlining.
  Node* InlinePropertyGetterCall(Node* receiver, Node* context,
                                 Node* frame_state, Node** effect,
                                 Node** control,
                                 ZoneVector<Node*>* if_exceptions,
                                 PropertyAccessInfo const& access_info);
  void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
                                Node* frame_state, Node** effect,
                                Node** control,
                                ZoneVector<Node*>* if_exceptions,
                                PropertyAccessInfo const& access_info);
  Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
                      Node* value, Node** effect, Node** control,
                      SharedFunctionInfoRef const& shared_info,
                      FunctionTemplateInfoRef const& function_template_info);

  // Construct the appropriate subgraph for element access.
  ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
                                        Node* value, Node* effect,
                                        Node* control,
                                        ElementAccessInfo const& access_info,
                                        KeyedAccessMode const& keyed_mode);

  // Construct appropriate subgraph to load from a String.
  Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
                               Node** effect, Node** control,
                               KeyedAccessLoadMode load_mode);

  // Construct appropriate subgraph to extend properties backing store.
  Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties,
                                          Node* effect, Node* control);

  // Construct appropriate subgraph to check that the {value} matches
  // the previously recorded {name} feedback.
  Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
                             Node* control);

  // Checks if we can turn the hole into undefined when loading an element
  // from an object with one of the {receiver_maps}; sets up appropriate
  // code dependencies and might use the array protector cell.
  bool CanTreatHoleAsUndefined(ZoneVector<Handle<Map>> const& receiver_maps);

  void RemoveImpossibleMaps(Node* object, ZoneVector<Handle<Map>>* maps) const;

  ElementAccessFeedback const& TryRefineElementAccessFeedback(
      ElementAccessFeedback const& feedback, Node* receiver,
      Node* effect) const;

  // Try to infer maps for the given {object} at the current {effect}.
  bool InferMaps(Node* object, Node* effect,
                 ZoneVector<Handle<Map>>* maps) const;

  // Try to infer a root map for the {object} independent of the current program
  // location.
  base::Optional<MapRef> InferRootMap(Node* object) const;

  // Checks if we know at compile time that the {receiver} either definitely
  // has the {prototype} in it's prototype chain, or the {receiver} definitely
  // doesn't have the {prototype} in it's prototype chain.
  enum InferHasInPrototypeChainResult {
    kIsInPrototypeChain,
    kIsNotInPrototypeChain,
    kMayBeInPrototypeChain
  };
  InferHasInPrototypeChainResult InferHasInPrototypeChain(
      Node* receiver, Node* effect, HeapObjectRef const& prototype);

  Node* BuildLoadPrototypeFromObject(Node* object, Node* effect, Node* control);

  Graph* graph() const;
  JSGraph* jsgraph() const { return jsgraph_; }

  JSHeapBroker* broker() const { return broker_; }
  Isolate* isolate() const;
  Factory* factory() const;
  CommonOperatorBuilder* common() const;
  JSOperatorBuilder* javascript() const;
  SimplifiedOperatorBuilder* simplified() const;
  Flags flags() const { return flags_; }
  Handle<JSGlobalObject> global_object() const { return global_object_; }
  Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
  NativeContextRef native_context() const {
    return broker()->target_native_context();
  }
  CompilationDependencies* dependencies() const { return dependencies_; }
  Zone* zone() const { return zone_; }
  Zone* shared_zone() const { return shared_zone_; }
  bool should_disallow_heap_access() const;

  JSGraph* const jsgraph_;
  JSHeapBroker* const broker_;
  Flags const flags_;
  Handle<JSGlobalObject> global_object_;
  Handle<JSGlobalProxy> global_proxy_;
  CompilationDependencies* const dependencies_;
  Zone* const zone_;
  Zone* const shared_zone_;
  TypeCache const* type_cache_;
};

DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
