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:
JSSpeculativeBinopBuilder(JSTypeHintLowering * lowering,const Operator * op,Node * left,Node * right,Node * effect,Node * control,FeedbackSlot slot)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
GetBinaryOperationHint()30 BinaryOperationHint GetBinaryOperationHint() {
31 DCHECK_EQ(FeedbackSlotKind::kBinaryOp, feedback_vector()->GetKind(slot_));
32 BinaryOpICNexus nexus(feedback_vector(), slot_);
33 return nexus.GetBinaryOperationFeedback();
34 }
35
GetBinaryNumberOperationHint(NumberOperationHint * hint)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
SpeculativeNumberOp(NumberOperationHint hint)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
BuildSpeculativeOperator(const Operator * op)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
jsgraph() const97 JSGraph* jsgraph() const { return lowering_->jsgraph(); }
graph() const98 Graph* graph() const { return jsgraph()->graph(); }
javascript()99 JSOperatorBuilder* javascript() { return jsgraph()->javascript(); }
simplified()100 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
common()101 CommonOperatorBuilder* common() { return jsgraph()->common(); }
feedback_vector() const102 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
JSTypeHintLowering(JSGraph * jsgraph,Handle<FeedbackVector> feedback_vector)116 JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph,
117 Handle<FeedbackVector> feedback_vector)
118 : jsgraph_(jsgraph), feedback_vector_(feedback_vector) {}
119
ReduceBinaryOperation(const Operator * op,Node * left,Node * right,Node * effect,Node * control,FeedbackSlot slot)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