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