OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
6 #include "src/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
7 #include "src/compiler/js-builtin-reducer.h" | 7 #include "src/compiler/js-builtin-reducer.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/node-aux-data-inl.h" | 9 #include "src/compiler/node-aux-data-inl.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 void SwapInputs() { | 107 void SwapInputs() { |
108 Node* l = left(); | 108 Node* l = left(); |
109 Node* r = right(); | 109 Node* r = right(); |
110 node_->ReplaceInput(0, r); | 110 node_->ReplaceInput(0, r); |
111 node_->ReplaceInput(1, l); | 111 node_->ReplaceInput(1, l); |
112 std::swap(left_type_, right_type_); | 112 std::swap(left_type_, right_type_); |
113 } | 113 } |
114 | 114 |
115 // Remove all effect and control inputs and outputs to this node and change | 115 // Remove all effect and control inputs and outputs to this node and change |
116 // to the pure operator {op}, possibly inserting a boolean inversion. | 116 // to the pure operator {op}, possibly inserting a boolean inversion. |
117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false) { | 117 Reduction ChangeToPureOperator(const Operator* op, bool invert = false, |
118 Type* type = Type::Any()) { | |
118 DCHECK_EQ(0, op->EffectInputCount()); | 119 DCHECK_EQ(0, op->EffectInputCount()); |
119 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); | 120 DCHECK_EQ(false, OperatorProperties::HasContextInput(op)); |
120 DCHECK_EQ(0, op->ControlInputCount()); | 121 DCHECK_EQ(0, op->ControlInputCount()); |
121 DCHECK_EQ(2, op->ValueInputCount()); | 122 DCHECK_EQ(2, op->ValueInputCount()); |
122 | 123 |
123 // Remove the effects from the node, if any, and update its effect usages. | 124 // Remove the effects from the node, if any, and update its effect usages. |
124 if (node_->op()->EffectInputCount() > 0) { | 125 if (node_->op()->EffectInputCount() > 0) { |
125 RelaxEffects(node_); | 126 RelaxEffects(node_); |
126 } | 127 } |
127 // Remove the inputs corresponding to context, effect, and control. | 128 // Remove the inputs corresponding to context, effect, and control. |
128 NodeProperties::RemoveNonValueInputs(node_); | 129 NodeProperties::RemoveNonValueInputs(node_); |
129 // Finally, update the operator to the new one. | 130 // Finally, update the operator to the new one. |
130 node_->set_op(op); | 131 node_->set_op(op); |
131 | 132 |
133 // TODO(jarin): Narrow the type after patching the operator. | |
Jarin
2014/12/04 10:43:01
This is not really a big fat TODO. Could you write
Benedikt Meurer
2014/12/04 11:19:01
Done.
| |
134 Bounds const bounds = NodeProperties::GetBounds(node_); | |
135 NodeProperties::SetBounds(node_, Bounds::NarrowUpper(bounds, type, zone())); | |
136 | |
132 if (invert) { | 137 if (invert) { |
133 // Insert an boolean not to invert the value. | 138 // Insert an boolean not to invert the value. |
134 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); | 139 Node* value = graph()->NewNode(simplified()->BooleanNot(), node_); |
135 node_->ReplaceUses(value); | 140 node_->ReplaceUses(value); |
136 // Note: ReplaceUses() smashes all uses, so smash it back here. | 141 // Note: ReplaceUses() smashes all uses, so smash it back here. |
137 value->ReplaceInput(0, node_); | 142 value->ReplaceInput(0, node_); |
138 return lowering_->ReplaceWith(value); | 143 return lowering_->ReplaceWith(value); |
139 } | 144 } |
140 return lowering_->Changed(node_); | 145 return lowering_->Changed(node_); |
141 } | 146 } |
Jarin
2014/12/04 10:43:01
Insert an empty line here?
Benedikt Meurer
2014/12/04 11:19:01
Done.
| |
147 Reduction ChangeToPureOperator(const Operator* op, Type* type) { | |
148 return ChangeToPureOperator(op, false, type); | |
149 } | |
142 | 150 |
143 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } | 151 bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); } |
144 | 152 |
145 bool BothInputsAre(Type* t) { | 153 bool BothInputsAre(Type* t) { |
146 return left_type_->Is(t) && right_type_->Is(t); | 154 return left_type_->Is(t) && right_type_->Is(t); |
147 } | 155 } |
148 | 156 |
149 bool OneInputCannotBe(Type* t) { | 157 bool OneInputCannotBe(Type* t) { |
150 return !left_type_->Maybe(t) || !right_type_->Maybe(t); | 158 return !left_type_->Maybe(t) || !right_type_->Maybe(t); |
151 } | 159 } |
152 | 160 |
153 bool NeitherInputCanBe(Type* t) { | 161 bool NeitherInputCanBe(Type* t) { |
154 return !left_type_->Maybe(t) && !right_type_->Maybe(t); | 162 return !left_type_->Maybe(t) && !right_type_->Maybe(t); |
155 } | 163 } |
156 | 164 |
157 Node* effect() { return NodeProperties::GetEffectInput(node_); } | 165 Node* effect() { return NodeProperties::GetEffectInput(node_); } |
158 Node* control() { return NodeProperties::GetControlInput(node_); } | 166 Node* control() { return NodeProperties::GetControlInput(node_); } |
159 Node* context() { return NodeProperties::GetContextInput(node_); } | 167 Node* context() { return NodeProperties::GetContextInput(node_); } |
160 Node* left() { return NodeProperties::GetValueInput(node_, 0); } | 168 Node* left() { return NodeProperties::GetValueInput(node_, 0); } |
161 Node* right() { return NodeProperties::GetValueInput(node_, 1); } | 169 Node* right() { return NodeProperties::GetValueInput(node_, 1); } |
162 Type* left_type() { return left_type_; } | 170 Type* left_type() { return left_type_; } |
163 Type* right_type() { return right_type_; } | 171 Type* right_type() { return right_type_; } |
164 | 172 |
165 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } | 173 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } |
166 Graph* graph() { return lowering_->graph(); } | 174 Graph* graph() const { return lowering_->graph(); } |
167 JSGraph* jsgraph() { return lowering_->jsgraph(); } | 175 JSGraph* jsgraph() { return lowering_->jsgraph(); } |
168 JSOperatorBuilder* javascript() { return lowering_->javascript(); } | 176 JSOperatorBuilder* javascript() { return lowering_->javascript(); } |
169 MachineOperatorBuilder* machine() { return lowering_->machine(); } | 177 MachineOperatorBuilder* machine() { return lowering_->machine(); } |
178 Zone* zone() const { return graph()->zone(); } | |
170 | 179 |
171 private: | 180 private: |
172 JSTypedLowering* lowering_; // The containing lowering instance. | 181 JSTypedLowering* lowering_; // The containing lowering instance. |
173 Node* node_; // The original node. | 182 Node* node_; // The original node. |
174 Type* left_type_; // Cache of the left input's type. | 183 Type* left_type_; // Cache of the left input's type. |
175 Type* right_type_; // Cache of the right input's type. | 184 Type* right_type_; // Cache of the right input's type. |
176 | 185 |
177 Node* ConvertToString(Node* node) { | 186 Node* ConvertToString(Node* node) { |
178 // Avoid introducing too many eager ToString() operations. | 187 // Avoid introducing too many eager ToString() operations. |
179 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 188 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 void update_effect(Node* effect) { | 220 void update_effect(Node* effect) { |
212 NodeProperties::ReplaceEffectInput(node_, effect); | 221 NodeProperties::ReplaceEffectInput(node_, effect); |
213 } | 222 } |
214 }; | 223 }; |
215 | 224 |
216 | 225 |
217 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { | 226 Reduction JSTypedLowering::ReduceJSAdd(Node* node) { |
218 JSBinopReduction r(this, node); | 227 JSBinopReduction r(this, node); |
219 if (r.BothInputsAre(Type::Number())) { | 228 if (r.BothInputsAre(Type::Number())) { |
220 // JSAdd(x:number, y:number) => NumberAdd(x, y) | 229 // JSAdd(x:number, y:number) => NumberAdd(x, y) |
221 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 230 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
222 } | 231 } |
223 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 232 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
224 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { | 233 if (r.BothInputsAre(Type::Primitive()) && r.NeitherInputCanBe(maybe_string)) { |
225 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) | 234 // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) |
226 r.ConvertInputsToNumber(); | 235 r.ConvertInputsToNumber(); |
227 return r.ChangeToPureOperator(simplified()->NumberAdd()); | 236 return r.ChangeToPureOperator(simplified()->NumberAdd(), Type::Number()); |
228 } | 237 } |
229 #if 0 | 238 #if 0 |
230 // TODO(turbofan): General ToNumber disabled for now because: | 239 // TODO(turbofan): General ToNumber disabled for now because: |
231 // a) The inserted ToNumber operation screws up observability of valueOf. | 240 // a) The inserted ToNumber operation screws up observability of valueOf. |
232 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. | 241 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
233 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); | 242 Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone()); |
234 if (r.NeitherInputCanBe(maybe_string)) { | 243 if (r.NeitherInputCanBe(maybe_string)) { |
235 ... | 244 ... |
236 } | 245 } |
237 #endif | 246 #endif |
(...skipping 18 matching lines...) Expand all Loading... | |
256 JSBinopReduction r(this, node); | 265 JSBinopReduction r(this, node); |
257 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { | 266 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(zero_range_)) { |
258 // TODO(jarin): Propagate frame state input from non-primitive input node to | 267 // TODO(jarin): Propagate frame state input from non-primitive input node to |
259 // JSToNumber node. | 268 // JSToNumber node. |
260 // TODO(titzer): some Smi bitwise operations don't really require going | 269 // TODO(titzer): some Smi bitwise operations don't really require going |
261 // all the way to int32, which can save tagging/untagging for some | 270 // all the way to int32, which can save tagging/untagging for some |
262 // operations | 271 // operations |
263 // on some platforms. | 272 // on some platforms. |
264 // TODO(turbofan): make this heuristic configurable for code size. | 273 // TODO(turbofan): make this heuristic configurable for code size. |
265 r.ConvertInputsToInt32(true, true); | 274 r.ConvertInputsToInt32(true, true); |
266 return r.ChangeToPureOperator(machine()->Word32Or()); | 275 return r.ChangeToPureOperator(machine()->Word32Or(), Type::Integral32()); |
267 } | 276 } |
268 return NoChange(); | 277 return NoChange(); |
269 } | 278 } |
270 | 279 |
271 | 280 |
272 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { | 281 Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { |
273 JSBinopReduction r(this, node); | 282 JSBinopReduction r(this, node); |
274 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) { | 283 if (r.BothInputsAre(Type::Primitive()) || r.OneInputIs(one_range_)) { |
275 // TODO(jarin): Propagate frame state input from non-primitive input node to | 284 // TODO(jarin): Propagate frame state input from non-primitive input node to |
276 // JSToNumber node. | 285 // JSToNumber node. |
277 r.ConvertInputsToNumber(); | 286 r.ConvertInputsToNumber(); |
278 return r.ChangeToPureOperator(simplified()->NumberMultiply()); | 287 return r.ChangeToPureOperator(simplified()->NumberMultiply(), |
288 Type::Number()); | |
279 } | 289 } |
280 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 290 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
281 return NoChange(); | 291 return NoChange(); |
282 } | 292 } |
283 | 293 |
284 | 294 |
285 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, | 295 Reduction JSTypedLowering::ReduceNumberBinop(Node* node, |
286 const Operator* numberOp) { | 296 const Operator* numberOp) { |
287 JSBinopReduction r(this, node); | 297 JSBinopReduction r(this, node); |
288 if (r.BothInputsAre(Type::Primitive())) { | 298 if (r.BothInputsAre(Type::Primitive())) { |
289 r.ConvertInputsToNumber(); | 299 r.ConvertInputsToNumber(); |
290 return r.ChangeToPureOperator(numberOp); | 300 return r.ChangeToPureOperator(numberOp, Type::Number()); |
291 } | 301 } |
292 #if 0 | 302 #if 0 |
293 // TODO(turbofan): General ToNumber disabled for now because: | 303 // TODO(turbofan): General ToNumber disabled for now because: |
294 // a) The inserted ToNumber operation screws up observability of valueOf. | 304 // a) The inserted ToNumber operation screws up observability of valueOf. |
295 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. | 305 // b) Deoptimization at ToNumber doesn't have corresponding bailout id. |
296 if (r.OneInputIs(Type::Primitive())) { | 306 if (r.OneInputIs(Type::Primitive())) { |
297 // If at least one input is a primitive, then insert appropriate conversions | 307 // If at least one input is a primitive, then insert appropriate conversions |
298 // to number and reduce this operator to the given numeric one. | 308 // to number and reduce this operator to the given numeric one. |
299 // TODO(turbofan): make this heuristic configurable for code size. | 309 // TODO(turbofan): make this heuristic configurable for code size. |
300 r.ConvertInputsToNumber(); | 310 r.ConvertInputsToNumber(); |
301 return r.ChangeToPureOperator(numberOp); | 311 return r.ChangeToPureOperator(numberOp); |
302 } | 312 } |
303 #endif | 313 #endif |
304 // TODO(turbofan): relax/remove the effects of this operator in other cases. | 314 // TODO(turbofan): relax/remove the effects of this operator in other cases. |
305 return NoChange(); | 315 return NoChange(); |
306 } | 316 } |
307 | 317 |
308 | 318 |
309 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, | 319 Reduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed, |
310 bool right_signed, | 320 bool right_signed, |
311 const Operator* intOp) { | 321 const Operator* intOp) { |
312 JSBinopReduction r(this, node); | 322 JSBinopReduction r(this, node); |
313 if (r.BothInputsAre(Type::Primitive())) { | 323 if (r.BothInputsAre(Type::Primitive())) { |
314 // TODO(titzer): some Smi bitwise operations don't really require going | 324 // TODO(titzer): some Smi bitwise operations don't really require going |
315 // all the way to int32, which can save tagging/untagging for some | 325 // all the way to int32, which can save tagging/untagging for some |
316 // operations | 326 // operations |
317 // on some platforms. | 327 // on some platforms. |
318 // TODO(turbofan): make this heuristic configurable for code size. | 328 // TODO(turbofan): make this heuristic configurable for code size. |
319 r.ConvertInputsToInt32(left_signed, right_signed); | 329 r.ConvertInputsToInt32(left_signed, right_signed); |
320 return r.ChangeToPureOperator(intOp); | 330 return r.ChangeToPureOperator(intOp, Type::Integral32()); |
321 } | 331 } |
322 return NoChange(); | 332 return NoChange(); |
323 } | 333 } |
324 | 334 |
325 | 335 |
326 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, | 336 Reduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed, |
327 const Operator* shift_op) { | 337 const Operator* shift_op) { |
328 JSBinopReduction r(this, node); | 338 JSBinopReduction r(this, node); |
329 if (r.BothInputsAre(Type::Primitive())) { | 339 if (r.BothInputsAre(Type::Primitive())) { |
330 r.ConvertInputsForShift(left_signed); | 340 r.ConvertInputsForShift(left_signed); |
331 return r.ChangeToPureOperator(shift_op); | 341 return r.ChangeToPureOperator(shift_op, Type::Integral32()); |
332 } | 342 } |
333 return NoChange(); | 343 return NoChange(); |
334 } | 344 } |
335 | 345 |
336 | 346 |
337 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { | 347 Reduction JSTypedLowering::ReduceJSComparison(Node* node) { |
338 JSBinopReduction r(this, node); | 348 JSBinopReduction r(this, node); |
339 if (r.BothInputsAre(Type::String())) { | 349 if (r.BothInputsAre(Type::String())) { |
340 // If both inputs are definitely strings, perform a string comparison. | 350 // If both inputs are definitely strings, perform a string comparison. |
341 const Operator* stringOp; | 351 const Operator* stringOp; |
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
899 | 909 |
900 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { | 910 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { |
901 if (rhs == 0) return lhs; | 911 if (rhs == 0) return lhs; |
902 return graph()->NewNode(machine()->Word32Shl(), lhs, | 912 return graph()->NewNode(machine()->Word32Shl(), lhs, |
903 jsgraph()->Int32Constant(rhs)); | 913 jsgraph()->Int32Constant(rhs)); |
904 } | 914 } |
905 | 915 |
906 } // namespace compiler | 916 } // namespace compiler |
907 } // namespace internal | 917 } // namespace internal |
908 } // namespace v8 | 918 } // namespace v8 |
OLD | NEW |