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