• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
6 #define V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
7 
8 #include "src/base/flags.h"
9 #include "src/compiler/graph-reducer.h"
10 #include "src/deoptimizer/deoptimize-reason.h"
11 #include "src/handles/handles.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // Forward declarations.
17 class FeedbackSlot;
18 
19 namespace compiler {
20 
21 // Forward declarations.
22 class JSGraph;
23 class Node;
24 class Operator;
25 
26 // The type-hint lowering consumes feedback about high-level operations in order
27 // to potentially emit nodes using speculative simplified operators in favor of
28 // the generic JavaScript operators.
29 //
30 // This lowering is implemented as an early reduction and can be applied before
31 // nodes are placed into the initial graph. It provides the ability to shortcut
32 // the JavaScript-level operators and directly emit simplified-level operators
33 // even during initial graph building. This is the reason this lowering doesn't
34 // follow the interface of the reducer framework used after graph construction.
35 // The result of the lowering is encapsulated in
36 // {the JSTypeHintLowering::LoweringResult} class.
37 class JSTypeHintLowering {
38  public:
39   // Flags that control the mode of operation.
40   enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 1 };
41   using Flags = base::Flags<Flag>;
42 
43   JSTypeHintLowering(JSHeapBroker* broker, JSGraph* jsgraph,
44                      FeedbackVectorRef feedback_vector, Flags flags);
45   JSTypeHintLowering(const JSTypeHintLowering&) = delete;
46   JSTypeHintLowering& operator=(const JSTypeHintLowering&) = delete;
47 
48   // {LoweringResult} describes the result of lowering. The following outcomes
49   // are possible:
50   //
51   // - operation was lowered to a side-effect-free operation, the resulting
52   //   value, effect and control can be obtained by the {value}, {effect} and
53   //   {control} methods.
54   //
55   // - operation was lowered to a graph exit (deoptimization). The caller
56   //   should connect {effect} and {control} nodes to the end.
57   //
58   // - no lowering happened. The caller needs to create the generic version
59   //   of the operation.
60   class LoweringResult {
61    public:
value()62     Node* value() const { return value_; }
effect()63     Node* effect() const { return effect_; }
control()64     Node* control() const { return control_; }
65 
Changed()66     bool Changed() const { return kind_ != LoweringResultKind::kNoChange; }
IsExit()67     bool IsExit() const { return kind_ == LoweringResultKind::kExit; }
IsSideEffectFree()68     bool IsSideEffectFree() const {
69       return kind_ == LoweringResultKind::kSideEffectFree;
70     }
71 
SideEffectFree(Node * value,Node * effect,Node * control)72     static LoweringResult SideEffectFree(Node* value, Node* effect,
73                                          Node* control) {
74       DCHECK_NOT_NULL(effect);
75       DCHECK_NOT_NULL(control);
76       DCHECK(value->op()->HasProperty(Operator::kNoThrow));
77       return LoweringResult(LoweringResultKind::kSideEffectFree, value, effect,
78                             control);
79     }
80 
NoChange()81     static LoweringResult NoChange() {
82       return LoweringResult(LoweringResultKind::kNoChange, nullptr, nullptr,
83                             nullptr);
84     }
85 
Exit(Node * control)86     static LoweringResult Exit(Node* control) {
87       return LoweringResult(LoweringResultKind::kExit, nullptr, nullptr,
88                             control);
89     }
90 
91    private:
92     enum class LoweringResultKind { kNoChange, kSideEffectFree, kExit };
93 
LoweringResult(LoweringResultKind kind,Node * value,Node * effect,Node * control)94     LoweringResult(LoweringResultKind kind, Node* value, Node* effect,
95                    Node* control)
96         : kind_(kind), value_(value), effect_(effect), control_(control) {}
97 
98     LoweringResultKind kind_;
99     Node* value_;
100     Node* effect_;
101     Node* control_;
102   };
103 
104   // Potential reduction of unary operations (e.g. negation).
105   LoweringResult ReduceUnaryOperation(const Operator* op, Node* operand,
106                                       Node* effect, Node* control,
107                                       FeedbackSlot slot) const;
108 
109   // Potential reduction of binary (arithmetic, logical, shift and relational
110   // comparison) operations.
111   LoweringResult ReduceBinaryOperation(const Operator* op, Node* left,
112                                        Node* right, Node* effect, Node* control,
113                                        FeedbackSlot slot) const;
114 
115   // Potential reduction to for..in operations
116   LoweringResult ReduceForInNextOperation(Node* receiver, Node* cache_array,
117                                           Node* cache_type, Node* index,
118                                           Node* effect, Node* control,
119                                           FeedbackSlot slot) const;
120   LoweringResult ReduceForInPrepareOperation(Node* enumerator, Node* effect,
121                                              Node* control,
122                                              FeedbackSlot slot) const;
123 
124   // Potential reduction to ToNumber operations
125   LoweringResult ReduceToNumberOperation(Node* value, Node* effect,
126                                          Node* control,
127                                          FeedbackSlot slot) const;
128 
129   // Potential reduction of call operations.
130   LoweringResult ReduceCallOperation(const Operator* op, Node* const* args,
131                                      int arg_count, Node* effect, Node* control,
132                                      FeedbackSlot slot) const;
133 
134   // Potential reduction of construct operations.
135   LoweringResult ReduceConstructOperation(const Operator* op, Node* const* args,
136                                           int arg_count, Node* effect,
137                                           Node* control,
138                                           FeedbackSlot slot) const;
139 
140   // Potential reduction of property access and call operations.
141   LoweringResult ReduceGetIteratorOperation(const Operator* op, Node* obj,
142                                             Node* effect, Node* control,
143                                             FeedbackSlot load_slot,
144                                             FeedbackSlot call_slot) const;
145 
146   // Potential reduction of property access operations.
147   LoweringResult ReduceLoadNamedOperation(const Operator* op, Node* effect,
148                                           Node* control,
149                                           FeedbackSlot slot) const;
150   LoweringResult ReduceLoadKeyedOperation(const Operator* op, Node* obj,
151                                           Node* key, Node* effect,
152                                           Node* control,
153                                           FeedbackSlot slot) const;
154   LoweringResult ReduceStoreNamedOperation(const Operator* op, Node* obj,
155                                            Node* val, Node* effect,
156                                            Node* control,
157                                            FeedbackSlot slot) const;
158   LoweringResult ReduceStoreKeyedOperation(const Operator* op, Node* obj,
159                                            Node* key, Node* val, Node* effect,
160                                            Node* control,
161                                            FeedbackSlot slot) const;
162 
163  private:
164   friend class JSSpeculativeBinopBuilder;
165 
166   BinaryOperationHint GetBinaryOperationHint(FeedbackSlot slot) const;
167   CompareOperationHint GetCompareOperationHint(FeedbackSlot slot) const;
168   Node* BuildDeoptIfFeedbackIsInsufficient(FeedbackSlot slot, Node* effect,
169                                            Node* control,
170                                            DeoptimizeReason reson) const;
171 
broker()172   JSHeapBroker* broker() const { return broker_; }
jsgraph()173   JSGraph* jsgraph() const { return jsgraph_; }
174   Isolate* isolate() const;
flags()175   Flags flags() const { return flags_; }
feedback_vector()176   FeedbackVectorRef const& feedback_vector() const { return feedback_vector_; }
177 
178   JSHeapBroker* const broker_;
179   JSGraph* const jsgraph_;
180   Flags const flags_;
181   FeedbackVectorRef const feedback_vector_;
182 };
183 
184 }  // namespace compiler
185 }  // namespace internal
186 }  // namespace v8
187 
188 #endif  // V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
189