summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/js-type-hint-lowering.h
blob: 3e46fb2ec2a19cc3738888a54ab9fcda30e444ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
75
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// 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/deoptimizer/deoptimize-reason.h"
#include "src/handles/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 };
  using Flags = base::Flags<Flag>;

  JSTypeHintLowering(JSHeapBroker* broker, JSGraph* jsgraph,
                     FeedbackVectorRef 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 unary operations (e.g. negation).
  LoweringResult ReduceUnaryOperation(const Operator* op, Node* operand,
                                      Node* effect, Node* control,
                                      FeedbackSlot slot) const;

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

  BinaryOperationHint GetBinaryOperationHint(FeedbackSlot slot) const;
  CompareOperationHint GetCompareOperationHint(FeedbackSlot slot) const;
  Node* TryBuildSoftDeopt(FeedbackSlot slot, Node* effect, Node* control,
                          DeoptimizeReason reson) const;

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

  JSHeapBroker* const broker_;
  JSGraph* const jsgraph_;
  Flags const flags_;
  FeedbackVectorRef const feedback_vector_;

  DISALLOW_COPY_AND_ASSIGN(JSTypeHintLowering);
};

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

#endif  // V8_COMPILER_JS_TYPE_HINT_LOWERING_H_