js-type-hint-lowering.h 7.82 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include "src/base/flags.h"
9
#include "src/compiler/graph-reducer.h"
10
#include "src/deoptimizer/deoptimize-reason.h"
11 12 13

namespace v8 {
namespace internal {
14 15 16 17

// Forward declarations.
class FeedbackSlot;

18 19 20 21
namespace compiler {

// Forward declarations.
class JSGraph;
22 23
class Node;
class Operator;
24

25 26 27
// 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.
28 29 30 31 32 33
//
// 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.
34 35
// The result of the lowering is encapsulated in
// {the JSTypeHintLowering::LoweringResult} class.
36 37
class JSTypeHintLowering {
 public:
38 39
  // Flags that control the mode of operation.
  enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 1 };
40
  using Flags = base::Flags<Flag>;
41

42 43
  JSTypeHintLowering(JSHeapBroker* broker, JSGraph* jsgraph,
                     FeedbackVectorRef feedback_vector, Flags flags);
44 45
  JSTypeHintLowering(const JSTypeHintLowering&) = delete;
  JSTypeHintLowering& operator=(const JSTypeHintLowering&) = delete;
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
  // {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);
75
      DCHECK(value->op()->HasProperty(Operator::kNoThrow));
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
      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_;
  };

103 104 105 106 107
  // Potential reduction of unary operations (e.g. negation).
  LoweringResult ReduceUnaryOperation(const Operator* op, Node* operand,
                                      Node* effect, Node* control,
                                      FeedbackSlot slot) const;

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

114
  // Potential reduction to for..in operations
115 116 117 118
  LoweringResult ReduceForInNextOperation(Node* receiver, Node* cache_array,
                                          Node* cache_type, Node* index,
                                          Node* effect, Node* control,
                                          FeedbackSlot slot) const;
119 120 121
  LoweringResult ReduceForInPrepareOperation(Node* enumerator, Node* effect,
                                             Node* control,
                                             FeedbackSlot slot) const;
122

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

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

133 134 135 136 137
  // Potential reduction of construct operations.
  LoweringResult ReduceConstructOperation(const Operator* op, Node* const* args,
                                          int arg_count, Node* effect,
                                          Node* control,
                                          FeedbackSlot slot) const;
138 139 140 141 142 143 144

  // Potential reduction of property access and call operations.
  LoweringResult ReduceGetIteratorOperation(const Operator* op, Node* obj,
                                            Node* effect, Node* control,
                                            FeedbackSlot load_slot,
                                            FeedbackSlot call_slot) const;

145
  // Potential reduction of property access operations.
146 147
  LoweringResult ReduceLoadNamedOperation(const Operator* op, Node* effect,
                                          Node* control,
148 149 150 151 152 153 154 155 156 157 158 159 160
                                          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;
161 162 163 164

 private:
  friend class JSSpeculativeBinopBuilder;

165 166
  BinaryOperationHint GetBinaryOperationHint(FeedbackSlot slot) const;
  CompareOperationHint GetCompareOperationHint(FeedbackSlot slot) const;
167 168 169
  Node* BuildDeoptIfFeedbackIsInsufficient(FeedbackSlot slot, Node* effect,
                                           Node* control,
                                           DeoptimizeReason reson) const;
170 171

  JSHeapBroker* broker() const { return broker_; }
172
  JSGraph* jsgraph() const { return jsgraph_; }
173
  Isolate* isolate() const;
174
  Flags flags() const { return flags_; }
175
  FeedbackVectorRef const& feedback_vector() const { return feedback_vector_; }
176

177 178
  JSHeapBroker* const broker_;
  JSGraph* const jsgraph_;
179
  Flags const flags_;
180
  FeedbackVectorRef const feedback_vector_;
181 182 183 184 185 186 187
};

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

#endif  // V8_COMPILER_JS_TYPE_HINT_LOWERING_H_