// 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_COMPILER_LOAD_ELIMINATION_H_
#define V8_COMPILER_LOAD_ELIMINATION_H_

#include "src/base/compiler-specific.h"
#include "src/compiler/graph-reducer.h"
#include "src/globals.h"
#include "src/machine-type.h"
#include "src/zone/zone-handle-set.h"

namespace v8 {
namespace internal {

// Forward declarations.
class Factory;

namespace compiler {

// Forward declarations.
class CommonOperatorBuilder;
struct FieldAccess;
class Graph;
class JSGraph;

class V8_EXPORT_PRIVATE LoadElimination final
    : public NON_EXPORTED_BASE(AdvancedReducer) {
 public:
  LoadElimination(Editor* editor, JSGraph* jsgraph, Zone* zone)
      : AdvancedReducer(editor), node_states_(zone), jsgraph_(jsgraph) {}
  ~LoadElimination() final {}

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

  Reduction Reduce(Node* node) final;

 private:
  static const size_t kMaxTrackedChecks = 8;

  // Abstract state to approximate the current state of checks that are
  // only invalidated by calls, i.e. array buffer neutering checks, along
  // the effect paths through the graph.
  class AbstractChecks final : public ZoneObject {
   public:
    explicit AbstractChecks(Zone* zone) {
      for (size_t i = 0; i < arraysize(nodes_); ++i) {
        nodes_[i] = nullptr;
      }
    }
    AbstractChecks(Node* node, Zone* zone) : AbstractChecks(zone) {
      nodes_[next_index_++] = node;
    }

    AbstractChecks const* Extend(Node* node, Zone* zone) const {
      AbstractChecks* that = new (zone) AbstractChecks(*this);
      that->nodes_[that->next_index_] = node;
      that->next_index_ = (that->next_index_ + 1) % arraysize(nodes_);
      return that;
    }
    Node* Lookup(Node* node) const;
    bool Equals(AbstractChecks const* that) const;
    AbstractChecks const* Merge(AbstractChecks const* that, Zone* zone) const;

    void Print() const;

   private:
    Node* nodes_[kMaxTrackedChecks];
    size_t next_index_ = 0;
  };

  static const size_t kMaxTrackedElements = 8;

  // Abstract state to approximate the current state of an element along the
  // effect paths through the graph.
  class AbstractElements final : public ZoneObject {
   public:
    explicit AbstractElements(Zone* zone) {
      for (size_t i = 0; i < arraysize(elements_); ++i) {
        elements_[i] = Element();
      }
    }
    AbstractElements(Node* object, Node* index, Node* value,
                     MachineRepresentation representation, Zone* zone)
        : AbstractElements(zone) {
      elements_[next_index_++] = Element(object, index, value, representation);
    }

    AbstractElements const* Extend(Node* object, Node* index, Node* value,
                                   MachineRepresentation representation,
                                   Zone* zone) const {
      AbstractElements* that = new (zone) AbstractElements(*this);
      that->elements_[that->next_index_] =
          Element(object, index, value, representation);
      that->next_index_ = (that->next_index_ + 1) % arraysize(elements_);
      return that;
    }
    Node* Lookup(Node* object, Node* index,
                 MachineRepresentation representation) const;
    AbstractElements const* Kill(Node* object, Node* index, Zone* zone) const;
    bool Equals(AbstractElements const* that) const;
    AbstractElements const* Merge(AbstractElements const* that,
                                  Zone* zone) const;

    void Print() const;

   private:
    struct Element {
      Element() {}
      Element(Node* object, Node* index, Node* value,
              MachineRepresentation representation)
          : object(object),
            index(index),
            value(value),
            representation(representation) {}

      Node* object = nullptr;
      Node* index = nullptr;
      Node* value = nullptr;
      MachineRepresentation representation = MachineRepresentation::kNone;
    };

    Element elements_[kMaxTrackedElements];
    size_t next_index_ = 0;
  };

  // Abstract state to approximate the current state of a certain field along
  // the effect paths through the graph.
  class AbstractField final : public ZoneObject {
   public:
    explicit AbstractField(Zone* zone) : info_for_node_(zone) {}
    AbstractField(Node* object, Node* value, MaybeHandle<Name> name, Zone* zone)
        : info_for_node_(zone) {
      info_for_node_.insert(std::make_pair(object, Field(value, name)));
    }

    AbstractField const* Extend(Node* object, Node* value,
                                MaybeHandle<Name> name, Zone* zone) const {
      AbstractField* that = new (zone) AbstractField(zone);
      that->info_for_node_ = this->info_for_node_;
      that->info_for_node_.insert(std::make_pair(object, Field(value, name)));
      return that;
    }
    Node* Lookup(Node* object) const;
    AbstractField const* Kill(Node* object, MaybeHandle<Name> name,
                              Zone* zone) const;
    bool Equals(AbstractField const* that) const {
      return this == that || this->info_for_node_ == that->info_for_node_;
    }
    AbstractField const* Merge(AbstractField const* that, Zone* zone) const {
      if (this->Equals(that)) return this;
      AbstractField* copy = new (zone) AbstractField(zone);
      for (auto this_it : this->info_for_node_) {
        Node* this_object = this_it.first;
        Field this_second = this_it.second;
        auto that_it = that->info_for_node_.find(this_object);
        if (that_it != that->info_for_node_.end() &&
            that_it->second == this_second) {
          copy->info_for_node_.insert(this_it);
        }
      }
      return copy;
    }

    void Print() const;

   private:
    struct Field {
      Field() {}
      Field(Node* value, MaybeHandle<Name> name) : value(value), name(name) {}

      bool operator==(const Field& other) const {
        return value == other.value && name.address() == other.name.address();
      }

      Node* value = nullptr;
      MaybeHandle<Name> name;
    };

    ZoneMap<Node*, Field> info_for_node_;
  };

  static size_t const kMaxTrackedFields = 32;

  // Abstract state to approximate the current map of an object along the
  // effect paths through the graph.
  class AbstractMaps final : public ZoneObject {
   public:
    explicit AbstractMaps(Zone* zone) : info_for_node_(zone) {}
    AbstractMaps(Node* object, ZoneHandleSet<Map> maps, Zone* zone)
        : info_for_node_(zone) {
      info_for_node_.insert(std::make_pair(object, maps));
    }

    AbstractMaps const* Extend(Node* object, ZoneHandleSet<Map> maps,
                               Zone* zone) const;
    bool Lookup(Node* object, ZoneHandleSet<Map>* object_maps) const;
    AbstractMaps const* Kill(Node* object, Zone* zone) const;
    bool Equals(AbstractMaps const* that) const {
      return this == that || this->info_for_node_ == that->info_for_node_;
    }
    AbstractMaps const* Merge(AbstractMaps const* that, Zone* zone) const;

    void Print() const;

   private:
    ZoneMap<Node*, ZoneHandleSet<Map>> info_for_node_;
  };

  class AbstractState final : public ZoneObject {
   public:
    AbstractState() {
      for (size_t i = 0; i < arraysize(fields_); ++i) {
        fields_[i] = nullptr;
      }
    }

    bool Equals(AbstractState const* that) const;
    void Merge(AbstractState const* that, Zone* zone);

    AbstractState const* AddMaps(Node* object, ZoneHandleSet<Map> maps,
                                 Zone* zone) const;
    AbstractState const* KillMaps(Node* object, Zone* zone) const;
    bool LookupMaps(Node* object, ZoneHandleSet<Map>* object_maps) const;

    AbstractState const* AddField(Node* object, size_t index, Node* value,
                                  MaybeHandle<Name> name, Zone* zone) const;
    AbstractState const* KillField(Node* object, size_t index,
                                   MaybeHandle<Name> name, Zone* zone) const;
    AbstractState const* KillFields(Node* object, MaybeHandle<Name> name,
                                    Zone* zone) const;
    Node* LookupField(Node* object, size_t index) const;

    AbstractState const* AddElement(Node* object, Node* index, Node* value,
                                    MachineRepresentation representation,
                                    Zone* zone) const;
    AbstractState const* KillElement(Node* object, Node* index,
                                     Zone* zone) const;
    Node* LookupElement(Node* object, Node* index,
                        MachineRepresentation representation) const;

    AbstractState const* AddCheck(Node* node, Zone* zone) const;
    Node* LookupCheck(Node* node) const;

    void Print() const;

   private:
    AbstractChecks const* checks_ = nullptr;
    AbstractElements const* elements_ = nullptr;
    AbstractField const* fields_[kMaxTrackedFields];
    AbstractMaps const* maps_ = nullptr;
  };

  class AbstractStateForEffectNodes final : public ZoneObject {
   public:
    explicit AbstractStateForEffectNodes(Zone* zone) : info_for_node_(zone) {}
    AbstractState const* Get(Node* node) const;
    void Set(Node* node, AbstractState const* state);

    Zone* zone() const { return info_for_node_.get_allocator().zone(); }

   private:
    ZoneVector<AbstractState const*> info_for_node_;
  };

  Reduction ReduceArrayBufferWasNeutered(Node* node);
  Reduction ReduceCheckMaps(Node* node);
  Reduction ReduceCompareMaps(Node* node);
  Reduction ReduceMapGuard(Node* node);
  Reduction ReduceEnsureWritableFastElements(Node* node);
  Reduction ReduceMaybeGrowFastElements(Node* node);
  Reduction ReduceTransitionElementsKind(Node* node);
  Reduction ReduceLoadField(Node* node);
  Reduction ReduceStoreField(Node* node);
  Reduction ReduceLoadElement(Node* node);
  Reduction ReduceStoreElement(Node* node);
  Reduction ReduceTransitionAndStoreElement(Node* node);
  Reduction ReduceStoreTypedElement(Node* node);
  Reduction ReduceEffectPhi(Node* node);
  Reduction ReduceStart(Node* node);
  Reduction ReduceOtherNode(Node* node);

  Reduction UpdateState(Node* node, AbstractState const* state);

  AbstractState const* ComputeLoopState(Node* node,
                                        AbstractState const* state) const;
  AbstractState const* UpdateStateForPhi(AbstractState const* state,
                                         Node* effect_phi, Node* phi);

  static int FieldIndexOf(int offset);
  static int FieldIndexOf(FieldAccess const& access);

  CommonOperatorBuilder* common() const;
  AbstractState const* empty_state() const { return &empty_state_; }
  Factory* factory() const;
  Graph* graph() const;
  JSGraph* jsgraph() const { return jsgraph_; }
  Zone* zone() const { return node_states_.zone(); }

  AbstractState const empty_state_;
  AbstractStateForEffectNodes node_states_;
  JSGraph* const jsgraph_;

  DISALLOW_COPY_AND_ASSIGN(LoadElimination);
};

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

#endif  // V8_COMPILER_LOAD_ELIMINATION_H_
