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