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/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/compiler/access-builder.h" | 6 #include "src/compiler/access-builder.h" |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-typed-lowering.h" | 8 #include "src/compiler/js-typed-lowering.h" |
9 #include "src/compiler/linkage.h" | 9 #include "src/compiler/linkage.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 | 100 |
101 void ConvertInputsToNumber(Node* frame_state) { | 101 void ConvertInputsToNumber(Node* frame_state) { |
102 // To convert the inputs to numbers, we have to provide frame states | 102 // To convert the inputs to numbers, we have to provide frame states |
103 // for lazy bailouts in the ToNumber conversions. | 103 // for lazy bailouts in the ToNumber conversions. |
104 // We use a little hack here: we take the frame state before the binary | 104 // We use a little hack here: we take the frame state before the binary |
105 // operation and use it to construct the frame states for the conversion | 105 // operation and use it to construct the frame states for the conversion |
106 // so that after the deoptimization, the binary operation IC gets | 106 // so that after the deoptimization, the binary operation IC gets |
107 // already converted values from full code. This way we are sure that we | 107 // already converted values from full code. This way we are sure that we |
108 // will not re-do any of the side effects. | 108 // will not re-do any of the side effects. |
109 | 109 |
110 Node* left_input = | 110 Node* left_input = nullptr; |
111 left_type()->Is(Type::PlainPrimitive()) | 111 Node* right_input = nullptr; |
112 ? ConvertPlainPrimitiveToNumber(left()) | 112 bool left_is_primitive = left_type()->Is(Type::PlainPrimitive()); |
113 : ConvertToNumber(left(), | 113 bool right_is_primitive = right_type()->Is(Type::PlainPrimitive()); |
114 CreateFrameStateForLeftInput(frame_state)); | 114 bool handles_exception = NodeProperties::IsExceptionalCall(node_); |
115 | 115 |
116 Node* right_input = | 116 if (!left_is_primitive && !right_is_primitive && handles_exception) { |
117 right_type()->Is(Type::PlainPrimitive()) | 117 ConvertBothInputsToNumber(&left_input, &right_input, frame_state); |
118 ? ConvertPlainPrimitiveToNumber(right()) | 118 } else { |
119 : ConvertToNumber(right(), CreateFrameStateForRightInput( | 119 left_input = left_is_primitive |
| 120 ? ConvertPlainPrimitiveToNumber(left()) |
| 121 : ConvertSingleInputToNumber( |
| 122 left(), CreateFrameStateForLeftInput(frame_state)); |
| 123 right_input = right_is_primitive |
| 124 ? ConvertPlainPrimitiveToNumber(right()) |
| 125 : ConvertSingleInputToNumber( |
| 126 right(), CreateFrameStateForRightInput( |
120 frame_state, left_input)); | 127 frame_state, left_input)); |
| 128 } |
121 | 129 |
122 node_->ReplaceInput(0, left_input); | 130 node_->ReplaceInput(0, left_input); |
123 node_->ReplaceInput(1, right_input); | 131 node_->ReplaceInput(1, right_input); |
124 } | 132 } |
125 | 133 |
126 void ConvertInputsToUI32(Signedness left_signedness, | 134 void ConvertInputsToUI32(Signedness left_signedness, |
127 Signedness right_signedness) { | 135 Signedness right_signedness) { |
128 node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness)); | 136 node_->ReplaceInput(0, ConvertToUI32(left(), left_signedness)); |
129 node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness)); | 137 node_->ReplaceInput(1, ConvertToUI32(right(), right_signedness)); |
130 } | 138 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 } | 227 } |
220 Type* right_type() { | 228 Type* right_type() { |
221 return NodeProperties::GetBounds(node_->InputAt(1)).upper; | 229 return NodeProperties::GetBounds(node_->InputAt(1)).upper; |
222 } | 230 } |
223 | 231 |
224 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } | 232 SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); } |
225 Graph* graph() const { return lowering_->graph(); } | 233 Graph* graph() const { return lowering_->graph(); } |
226 JSGraph* jsgraph() { return lowering_->jsgraph(); } | 234 JSGraph* jsgraph() { return lowering_->jsgraph(); } |
227 JSOperatorBuilder* javascript() { return lowering_->javascript(); } | 235 JSOperatorBuilder* javascript() { return lowering_->javascript(); } |
228 MachineOperatorBuilder* machine() { return lowering_->machine(); } | 236 MachineOperatorBuilder* machine() { return lowering_->machine(); } |
| 237 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
229 Zone* zone() const { return graph()->zone(); } | 238 Zone* zone() const { return graph()->zone(); } |
230 | 239 |
231 private: | 240 private: |
232 JSTypedLowering* lowering_; // The containing lowering instance. | 241 JSTypedLowering* lowering_; // The containing lowering instance. |
233 Node* node_; // The original node. | 242 Node* node_; // The original node. |
234 | 243 |
235 Node* ConvertToString(Node* node) { | 244 Node* ConvertToString(Node* node) { |
236 // Avoid introducing too many eager ToString() operations. | 245 // Avoid introducing too many eager ToString() operations. |
237 Reduction reduced = lowering_->ReduceJSToStringInput(node); | 246 Reduction reduced = lowering_->ReduceJSToStringInput(node); |
238 if (reduced.Changed()) return reduced.replacement(); | 247 if (reduced.Changed()) return reduced.replacement(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())); | 326 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())); |
318 // Avoid inserting too many eager ToNumber() operations. | 327 // Avoid inserting too many eager ToNumber() operations. |
319 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); | 328 Reduction const reduction = lowering_->ReduceJSToNumberInput(node); |
320 if (reduction.Changed()) return reduction.replacement(); | 329 if (reduction.Changed()) return reduction.replacement(); |
321 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. | 330 // TODO(jarin) Use PlainPrimitiveToNumber once we have it. |
322 return graph()->NewNode( | 331 return graph()->NewNode( |
323 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(), | 332 javascript()->ToNumber(), node, jsgraph()->NoContextConstant(), |
324 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); | 333 jsgraph()->EmptyFrameState(), graph()->start(), graph()->start()); |
325 } | 334 } |
326 | 335 |
327 Node* ConvertToNumber(Node* node, Node* frame_state) { | 336 Node* ConvertSingleInputToNumber(Node* node, Node* frame_state) { |
328 if (NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())) { | 337 DCHECK(!NodeProperties::GetBounds(node).upper->Is(Type::PlainPrimitive())); |
329 return ConvertPlainPrimitiveToNumber(node); | 338 Node* const n = graph()->NewNode(javascript()->ToNumber(), node, context(), |
330 } else { | 339 frame_state, effect(), control()); |
331 Node* const n = | 340 NodeProperties::ReplaceUses(node_, node_, node_, n, n); |
332 graph()->NewNode(javascript()->ToNumber(), node, context(), | 341 update_effect(n); |
333 frame_state, effect(), control()); | 342 return n; |
334 update_effect(n); | 343 } |
335 return n; | 344 |
| 345 void ConvertBothInputsToNumber(Node** left_result, Node** right_result, |
| 346 Node* frame_state) { |
| 347 Node* projections[2]; |
| 348 |
| 349 // Find {IfSuccess} and {IfException} continuations of the operation. |
| 350 NodeProperties::CollectControlProjections(node_, projections, 2); |
| 351 IfExceptionHint hint = OpParameter<IfExceptionHint>(projections[1]); |
| 352 Node* if_exception = projections[1]; |
| 353 Node* if_success = projections[0]; |
| 354 |
| 355 // Insert two ToNumber() operations that both potentially throw. |
| 356 Node* left_state = CreateFrameStateForLeftInput(frame_state); |
| 357 Node* left_conv = |
| 358 graph()->NewNode(javascript()->ToNumber(), left(), context(), |
| 359 left_state, effect(), control()); |
| 360 Node* left_success = graph()->NewNode(common()->IfSuccess(), left_conv); |
| 361 Node* right_state = CreateFrameStateForRightInput(frame_state, left_conv); |
| 362 Node* right_conv = |
| 363 graph()->NewNode(javascript()->ToNumber(), right(), context(), |
| 364 right_state, left_conv, left_success); |
| 365 Node* left_exception = |
| 366 graph()->NewNode(common()->IfException(hint), left_conv, left_conv); |
| 367 Node* right_exception = |
| 368 graph()->NewNode(common()->IfException(hint), right_conv, right_conv); |
| 369 NodeProperties::ReplaceControlInput(if_success, right_conv); |
| 370 update_effect(right_conv); |
| 371 |
| 372 // Wire conversions to existing {IfException} continuation. |
| 373 Node* exception_merge = if_exception; |
| 374 Node* exception_value = |
| 375 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), left_exception, |
| 376 right_exception, exception_merge); |
| 377 Node* exception_effect = |
| 378 graph()->NewNode(common()->EffectPhi(2), left_exception, |
| 379 right_exception, exception_merge); |
| 380 for (Edge edge : exception_merge->use_edges()) { |
| 381 if (NodeProperties::IsEffectEdge(edge)) edge.UpdateTo(exception_effect); |
| 382 if (NodeProperties::IsValueEdge(edge)) edge.UpdateTo(exception_value); |
336 } | 383 } |
| 384 NodeProperties::RemoveBounds(exception_merge); |
| 385 exception_merge->ReplaceInput(0, left_exception); |
| 386 exception_merge->ReplaceInput(1, right_exception); |
| 387 exception_merge->set_op(common()->Merge(2)); |
| 388 |
| 389 *left_result = left_conv; |
| 390 *right_result = right_conv; |
337 } | 391 } |
338 | 392 |
339 Node* ConvertToUI32(Node* node, Signedness signedness) { | 393 Node* ConvertToUI32(Node* node, Signedness signedness) { |
340 // Avoid introducing too many eager NumberToXXnt32() operations. | 394 // Avoid introducing too many eager NumberToXXnt32() operations. |
341 Type* type = NodeProperties::GetBounds(node).upper; | 395 Type* type = NodeProperties::GetBounds(node).upper; |
342 if (signedness == kSigned) { | 396 if (signedness == kSigned) { |
343 if (!type->Is(Type::Signed32())) { | 397 if (!type->Is(Type::Signed32())) { |
344 node = graph()->NewNode(simplified()->NumberToInt32(), node); | 398 node = graph()->NewNode(simplified()->NumberToInt32(), node); |
345 } | 399 } |
346 } else { | 400 } else { |
(...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1618 } | 1672 } |
1619 | 1673 |
1620 | 1674 |
1621 MachineOperatorBuilder* JSTypedLowering::machine() const { | 1675 MachineOperatorBuilder* JSTypedLowering::machine() const { |
1622 return jsgraph()->machine(); | 1676 return jsgraph()->machine(); |
1623 } | 1677 } |
1624 | 1678 |
1625 } // namespace compiler | 1679 } // namespace compiler |
1626 } // namespace internal | 1680 } // namespace internal |
1627 } // namespace v8 | 1681 } // namespace v8 |
OLD | NEW |