• 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 #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