// Copyright 2017 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_TYPE_HINT_LOWERING_H_
#define V8_COMPILER_JS_TYPE_HINT_LOWERING_H_

#include "src/base/flags.h"
#include "src/compiler/graph-reducer.h"
#include "src/deoptimize-reason.h"
#include "src/handles.h"

namespace v8 {
namespace internal {

// Forward declarations.
class FeedbackNexus;
class FeedbackSlot;

namespace compiler {

// Forward declarations.
class JSGraph;
class Node;
class Operator;

// The type-hint lowering consumes feedback about high-level operations in order
// to potentially emit nodes using speculative simplified operators in favor of
// the generic JavaScript operators.
//
// This lowering is implemented as an early reduction and can be applied before
// nodes are placed into the initial graph. It provides the ability to shortcut
// the JavaScript-level operators and directly emit simplified-level operators
// even during initial graph building. This is the reason this lowering doesn't
// follow the interface of the reducer framework used after graph construction.
// The result of the lowering is encapsulated in
// {the JSTypeHintLowering::LoweringResult} class.
class JSTypeHintLowering {
 public:
  // Flags that control the mode of operation.
  enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 1 };
  typedef base::Flags<Flag> Flags;

  JSTypeHintLowering(JSGraph* jsgraph, Handle<FeedbackVector> feedback_vector,
                     Flags flags);

  // {LoweringResult} describes the result of lowering. The following outcomes
  // are possible:
  //
  // - operation was lowered to a side-effect-free operation, the resulting
  //   value, effect and control can be obtained by the {value}, {effect} and
  //   {control} methods.
  //
  // - operation was lowered to a graph exit (deoptimization). The caller
  //   should connect {effect} and {control} nodes to the end.
  //
  // - no lowering happened. The caller needs to create the generic version
  //   of the operation.
  class LoweringResult {
   public:
    Node* value() const { return value_; }
    Node* effect() const { return effect_; }
    Node* control() const { return control_; }

    bool Changed() const { return kind_ != LoweringResultKind::kNoChange; }
    bool IsExit() const { return kind_ == LoweringResultKind::kExit; }
    bool IsSideEffectFree() const {
      return kind_ == LoweringResultKind::kSideEffectFree;
    }

    static LoweringResult SideEffectFree(Node* value, Node* effect,
                                         Node* control) {
      DCHECK_NOT_NULL(effect);
      DCHECK_NOT_NULL(control);
      return LoweringResult(LoweringResultKind::kSideEffectFree, value, effect,
                            control);
    }

    static LoweringResult NoChange() {
      return LoweringResult(LoweringResultKind::kNoChange, nullptr, nullptr,
                            nullptr);
    }

    static LoweringResult Exit(Node* control) {
      return LoweringResult(LoweringResultKind::kExit, nullptr, nullptr,
                            control);
    }

   private:
    enum class LoweringResultKind { kNoChange, kSideEffectFree, kExit };

    LoweringResult(LoweringResultKind kind, Node* value, Node* effect,
                   Node* control)
        : kind_(kind), value_(value), effect_(effect), control_(control) {}

    LoweringResultKind kind_;
    Node* value_;
    Node* effect_;
    Node* control_;
  };

  // Potential reduction of binary (arithmetic, logical, shift and relational
  // comparison) operations.
  LoweringResult ReduceBinaryOperation(const Operator* op, Node* left,
                                       Node* right, Node* effect, Node* control,
                                       FeedbackSlot slot) const;

  // Potential reduction to for..in operations
  LoweringResult ReduceForInNextOperation(Node* receiver, Node* cache_array,
                                          Node* cache_type, Node* index,
                                          Node* effect, Node* control,
                                          FeedbackSlot slot) const;
  LoweringResult ReduceForInPrepareOperation(Node* enumerator, Node* effect,
                                             Node* control,
                                             FeedbackSlot slot) const;

  // Potential reduction to ToNumber operations
  LoweringResult ReduceToNumberOperation(Node* value, Node* effect,
                                         Node* control,
                                         FeedbackSlot slot) const;

  // Potential reduction of call operations.
  LoweringResult ReduceCallOperation(const Operator* op, Node* const* args,
                                     int arg_count, Node* effect, Node* control,
                                     FeedbackSlot slot) const;

  // Potential reduction of construct operations.
  LoweringResult ReduceConstructOperation(const Operator* op, Node* const* args,
                                          int arg_count, Node* effect,
                                          Node* control,
                                          FeedbackSlot slot) const;
  // Potential reduction of property access operations.
  LoweringResult ReduceLoadNamedOperation(const Operator* op, Node* obj,
                                          Node* effect, Node* control,
                                          FeedbackSlot slot) const;
  LoweringResult ReduceLoadKeyedOperation(const Operator* op, Node* obj,
                                          Node* key, Node* effect,
                                          Node* control,
                                          FeedbackSlot slot) const;
  LoweringResult ReduceStoreNamedOperation(const Operator* op, Node* obj,
                                           Node* val, Node* effect,
                                           Node* control,
                                           FeedbackSlot slot) const;
  LoweringResult ReduceStoreKeyedOperation(const Operator* op, Node* obj,
                                           Node* key, Node* val, Node* effect,
                                           Node* control,
                                           FeedbackSlot slot) const;

 private:
  friend class JSSpeculativeBinopBuilder;
  Node* TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect, Node* control,
                          DeoptimizeReason reson) const;

  JSGraph* jsgraph() const { return jsgraph_; }
  Flags flags() const { return flags_; }
  const Handle<FeedbackVector>& feedback_vector() const {
    return feedback_vector_;
  }

  JSGraph* jsgraph_;
  Flags const flags_;
  Handle<FeedbackVector> feedback_vector_;

  DISALLOW_COPY_AND_ASSIGN(JSTypeHintLowering);
};

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

#endif  // V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
