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 #include "src/compiler/js-type-hint-lowering.h" 6 7 #include "src/compiler/js-graph.h" 8 #include "src/compiler/operator-properties.h" 9 #include "src/compiler/simplified-operator.h" 10 #include "src/feedback-vector.h" 11 #include "src/type-hints.h" 12 13 namespace v8 { 14 namespace internal { 15 namespace compiler { 16 17 class JSSpeculativeBinopBuilder final { 18 public: 19 JSSpeculativeBinopBuilder(JSTypeHintLowering* lowering, const Operator* op, 20 Node* left, Node* right, Node* effect, 21 Node* control, FeedbackSlot slot) 22 : lowering_(lowering), 23 op_(op), 24 left_(left), 25 right_(right), 26 effect_(effect), 27 control_(control), 28 slot_(slot) {} 29 30 BinaryOperationHint GetBinaryOperationHint() { 31 DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot_)); 32 BinaryOpICNexus nexus(feedback_vector(), slot_); 33 return nexus.GetBinaryOperationFeedback(); 34 } 35 36 bool GetBinaryNumberOperationHint(NumberOperationHint* hint) { 37 switch (GetBinaryOperationHint()) { 38 case BinaryOperationHint::kSignedSmall: 39 *hint = NumberOperationHint::kSignedSmall; 40 return true; 41 case BinaryOperationHint::kSigned32: 42 *hint = NumberOperationHint::kSigned32; 43 return true; 44 case BinaryOperationHint::kNumberOrOddball: 45 *hint = NumberOperationHint::kNumberOrOddball; 46 return true; 47 case BinaryOperationHint::kAny: 48 case BinaryOperationHint::kNone: 49 case BinaryOperationHint::kString: 50 break; 51 } 52 return false; 53 } 54 55 const Operator* SpeculativeNumberOp(NumberOperationHint hint) { 56 switch (op_->opcode()) { 57 case IrOpcode::kJSAdd: 58 return simplified()->SpeculativeNumberAdd(hint); 59 case IrOpcode::kJSSubtract: 60 return simplified()->SpeculativeNumberSubtract(hint); 61 case IrOpcode::kJSMultiply: 62 return simplified()->SpeculativeNumberMultiply(hint); 63 case IrOpcode::kJSDivide: 64 return simplified()->SpeculativeNumberDivide(hint); 65 case IrOpcode::kJSModulus: 66 return simplified()->SpeculativeNumberModulus(hint); 67 case IrOpcode::kJSBitwiseAnd: 68 return simplified()->SpeculativeNumberBitwiseAnd(hint); 69 case IrOpcode::kJSBitwiseOr: 70 return simplified()->SpeculativeNumberBitwiseOr(hint); 71 case IrOpcode::kJSBitwiseXor: 72 return simplified()->SpeculativeNumberBitwiseXor(hint); 73 case IrOpcode::kJSShiftLeft: 74 return simplified()->SpeculativeNumberShiftLeft(hint); 75 case IrOpcode::kJSShiftRight: 76 return simplified()->SpeculativeNumberShiftRight(hint); 77 case IrOpcode::kJSShiftRightLogical: 78 return simplified()->SpeculativeNumberShiftRightLogical(hint); 79 default: 80 break; 81 } 82 UNREACHABLE(); 83 return nullptr; 84 } 85 86 Node* BuildSpeculativeOperator(const Operator* op) { 87 DCHECK_EQ(2, op->ValueInputCount()); 88 DCHECK_EQ(1, op->EffectInputCount()); 89 DCHECK_EQ(1, op->ControlInputCount()); 90 DCHECK_EQ(false, OperatorProperties::HasFrameStateInput(op)); 91 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); 92 DCHECK_EQ(1, op->EffectOutputCount()); 93 DCHECK_EQ(0, op->ControlOutputCount()); 94 return graph()->NewNode(op, left_, right_, effect_, control_); 95 } 96 97 JSGraph* jsgraph() const { return lowering_->jsgraph(); } 98 Graph* graph() const { return jsgraph()->graph(); } 99 JSOperatorBuilder* javascript() { return jsgraph()->javascript(); } 100 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); } 101 CommonOperatorBuilder* common() { return jsgraph()->common(); } 102 const Handle<FeedbackVector>& feedback_vector() const { 103 return lowering_->feedback_vector(); 104 } 105 106 private: 107 JSTypeHintLowering* lowering_; 108 const Operator* op_; 109 Node* left_; 110 Node* right_; 111 Node* effect_; 112 Node* control_; 113 FeedbackSlot slot_; 114 }; 115 116 JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph, 117 Handle<FeedbackVector> feedback_vector) 118 : jsgraph_(jsgraph), feedback_vector_(feedback_vector) {} 119 120 Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op, 121 Node* left, Node* right, 122 Node* effect, Node* control, 123 FeedbackSlot slot) { 124 switch (op->opcode()) { 125 case IrOpcode::kJSBitwiseOr: 126 case IrOpcode::kJSBitwiseXor: 127 case IrOpcode::kJSBitwiseAnd: 128 case IrOpcode::kJSShiftLeft: 129 case IrOpcode::kJSShiftRight: 130 case IrOpcode::kJSShiftRightLogical: 131 case IrOpcode::kJSAdd: 132 case IrOpcode::kJSSubtract: 133 case IrOpcode::kJSMultiply: 134 case IrOpcode::kJSDivide: 135 case IrOpcode::kJSModulus: { 136 JSSpeculativeBinopBuilder b(this, op, left, right, effect, control, slot); 137 NumberOperationHint hint; 138 if (b.GetBinaryNumberOperationHint(&hint)) { 139 Node* node = b.BuildSpeculativeOperator(b.SpeculativeNumberOp(hint)); 140 return Reduction(node); 141 } 142 break; 143 } 144 default: 145 UNREACHABLE(); 146 break; 147 } 148 return Reduction(); 149 } 150 151 } // namespace compiler 152 } // namespace internal 153 } // namespace v8 154