| 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/change-lowering.h" | 5 #include "src/compiler/change-lowering.h" |
| 6 | 6 |
| 7 #include "src/address-map.h" | 7 #include "src/address-map.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 Node* control = graph()->start(); | 24 Node* control = graph()->start(); |
| 25 switch (node->opcode()) { | 25 switch (node->opcode()) { |
| 26 case IrOpcode::kChangeBitToBool: | 26 case IrOpcode::kChangeBitToBool: |
| 27 return ChangeBitToBool(node->InputAt(0), control); | 27 return ChangeBitToBool(node->InputAt(0), control); |
| 28 case IrOpcode::kChangeBoolToBit: | 28 case IrOpcode::kChangeBoolToBit: |
| 29 return ChangeBoolToBit(node->InputAt(0)); | 29 return ChangeBoolToBit(node->InputAt(0)); |
| 30 case IrOpcode::kChangeFloat64ToTagged: | 30 case IrOpcode::kChangeFloat64ToTagged: |
| 31 return ChangeFloat64ToTagged(node->InputAt(0), control); | 31 return ChangeFloat64ToTagged(node->InputAt(0), control); |
| 32 case IrOpcode::kChangeInt32ToTagged: | 32 case IrOpcode::kChangeInt32ToTagged: |
| 33 return ChangeInt32ToTagged(node->InputAt(0), control); | 33 return ChangeInt32ToTagged(node->InputAt(0), control); |
| 34 case IrOpcode::kChangeSmiToInt32: |
| 35 return ChangeSmiToInt32(node->InputAt(0)); |
| 34 case IrOpcode::kChangeTaggedToFloat64: | 36 case IrOpcode::kChangeTaggedToFloat64: |
| 35 return ChangeTaggedToFloat64(node->InputAt(0), control); | 37 return ChangeTaggedToFloat64(node->InputAt(0), control); |
| 36 case IrOpcode::kChangeTaggedToInt32: | 38 case IrOpcode::kChangeTaggedToInt32: |
| 37 return ChangeTaggedToUI32(node->InputAt(0), control, kSigned); | 39 return ChangeTaggedToUI32(node->InputAt(0), control, kSigned); |
| 38 case IrOpcode::kChangeTaggedToUint32: | 40 case IrOpcode::kChangeTaggedToUint32: |
| 39 return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned); | 41 return ChangeTaggedToUI32(node->InputAt(0), control, kUnsigned); |
| 40 case IrOpcode::kChangeUint32ToTagged: | 42 case IrOpcode::kChangeUint32ToTagged: |
| 41 return ChangeUint32ToTagged(node->InputAt(0), control); | 43 return ChangeUint32ToTagged(node->InputAt(0), control); |
| 42 case IrOpcode::kLoadField: | 44 case IrOpcode::kLoadField: |
| 43 return LoadField(node); | 45 return LoadField(node); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 | 116 |
| 115 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) { | 117 Node* ChangeLowering::ChangeInt32ToSmi(Node* value) { |
| 116 if (machine()->Is64()) { | 118 if (machine()->Is64()) { |
| 117 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); | 119 value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value); |
| 118 } | 120 } |
| 119 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); | 121 return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()); |
| 120 } | 122 } |
| 121 | 123 |
| 122 | 124 |
| 123 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { | 125 Node* ChangeLowering::ChangeSmiToFloat64(Node* value) { |
| 124 return ChangeInt32ToFloat64(ChangeSmiToInt32(value)); | 126 return ChangeInt32ToFloat64(ChangeSmiToWord32(value)); |
| 125 } | 127 } |
| 126 | 128 |
| 127 | 129 Node* ChangeLowering::ChangeSmiToWord32(Node* value) { |
| 128 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { | |
| 129 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); | 130 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); |
| 130 if (machine()->Is64()) { | 131 if (machine()->Is64()) { |
| 131 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); | 132 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); |
| 132 } | 133 } |
| 133 return value; | 134 return value; |
| 134 } | 135 } |
| 135 | 136 |
| 136 | 137 |
| 137 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { | 138 Node* ChangeLowering::ChangeUint32ToFloat64(Node* value) { |
| 138 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); | 139 return graph()->NewNode(machine()->ChangeUint32ToFloat64(), value); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 271 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 271 Node* vfalse = graph()->NewNode(common()->Projection(0), add); | 272 Node* vfalse = graph()->NewNode(common()->Projection(0), add); |
| 272 | 273 |
| 273 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 274 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
| 274 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 275 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 275 vtrue, vfalse, merge); | 276 vtrue, vfalse, merge); |
| 276 | 277 |
| 277 return Replace(phi); | 278 return Replace(phi); |
| 278 } | 279 } |
| 279 | 280 |
| 281 Reduction ChangeLowering::ChangeSmiToInt32(Node* value) { |
| 282 return Replace(ChangeSmiToWord32(value)); |
| 283 } |
| 280 | 284 |
| 281 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, | 285 Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control, |
| 282 Signedness signedness) { | 286 Signedness signedness) { |
| 283 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { | 287 if (NodeProperties::GetType(value)->Is(Type::TaggedSigned())) { |
| 284 return Replace(ChangeSmiToInt32(value)); | 288 return ChangeSmiToInt32(value); |
| 285 } | 289 } |
| 286 | 290 |
| 287 const Operator* op = (signedness == kSigned) | 291 const Operator* op = (signedness == kSigned) |
| 288 ? machine()->ChangeFloat64ToInt32() | 292 ? machine()->ChangeFloat64ToInt32() |
| 289 : machine()->ChangeFloat64ToUint32(); | 293 : machine()->ChangeFloat64ToUint32(); |
| 290 | 294 |
| 291 if (NodeProperties::GetType(value)->Is(Type::TaggedPointer()) && | 295 if (NodeProperties::GetType(value)->Is(Type::TaggedPointer()) && |
| 292 NodeProperties::GetType(value)->Is(Type::Number())) { | 296 NodeProperties::GetType(value)->Is(Type::Number())) { |
| 293 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control))); | 297 return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control))); |
| 294 } | 298 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 317 if_not_smi = | 321 if_not_smi = |
| 318 graph()->NewNode(common()->Merge(2), if_undefined, if_not_undefined); | 322 graph()->NewNode(common()->Merge(2), if_undefined, if_not_undefined); |
| 319 vnot_smi = | 323 vnot_smi = |
| 320 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 324 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 321 vundefined, vheap_number, if_not_smi); | 325 vundefined, vheap_number, if_not_smi); |
| 322 } else { | 326 } else { |
| 323 vnot_smi = graph()->NewNode(op, LoadHeapNumberValue(value, if_not_smi)); | 327 vnot_smi = graph()->NewNode(op, LoadHeapNumberValue(value, if_not_smi)); |
| 324 } | 328 } |
| 325 | 329 |
| 326 Node* if_smi = graph()->NewNode(common()->IfFalse(), branch); | 330 Node* if_smi = graph()->NewNode(common()->IfFalse(), branch); |
| 327 Node* vfrom_smi = ChangeSmiToInt32(value); | 331 Node* vfrom_smi = ChangeSmiToWord32(value); |
| 328 | 332 |
| 329 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); | 333 Node* merge = graph()->NewNode(common()->Merge(2), if_not_smi, if_smi); |
| 330 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 334 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 331 vnot_smi, vfrom_smi, merge); | 335 vnot_smi, vfrom_smi, merge); |
| 332 | 336 |
| 333 return Replace(phi); | 337 return Replace(phi); |
| 334 } | 338 } |
| 335 | 339 |
| 336 | 340 |
| 337 namespace { | |
| 338 | |
| 339 bool CanCover(Node* value, IrOpcode::Value opcode) { | |
| 340 if (value->opcode() != opcode) return false; | |
| 341 bool first = true; | |
| 342 for (Edge const edge : value->use_edges()) { | |
| 343 if (NodeProperties::IsControlEdge(edge)) continue; | |
| 344 if (NodeProperties::IsEffectEdge(edge)) continue; | |
| 345 DCHECK(NodeProperties::IsValueEdge(edge)); | |
| 346 if (!first) return false; | |
| 347 first = false; | |
| 348 } | |
| 349 return true; | |
| 350 } | |
| 351 | |
| 352 } // namespace | |
| 353 | |
| 354 | |
| 355 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { | 341 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) { |
| 356 if (CanCover(value, IrOpcode::kJSToNumber)) { | |
| 357 // ChangeTaggedToFloat64(JSToNumber(x)) => | |
| 358 // if IsSmi(x) then ChangeSmiToFloat64(x) | |
| 359 // else let y = JSToNumber(x) in | |
| 360 // if IsSmi(y) then ChangeSmiToFloat64(y) | |
| 361 // else LoadHeapNumberValue(y) | |
| 362 Node* const object = NodeProperties::GetValueInput(value, 0); | |
| 363 Node* const context = NodeProperties::GetContextInput(value); | |
| 364 Node* const frame_state = NodeProperties::GetFrameStateInput(value, 0); | |
| 365 Node* const effect = NodeProperties::GetEffectInput(value); | |
| 366 Node* const control = NodeProperties::GetControlInput(value); | |
| 367 | |
| 368 const Operator* merge_op = common()->Merge(2); | |
| 369 const Operator* ephi_op = common()->EffectPhi(2); | |
| 370 const Operator* phi_op = common()->Phi(MachineRepresentation::kFloat64, 2); | |
| 371 | |
| 372 Node* check1 = TestNotSmi(object); | |
| 373 Node* branch1 = | |
| 374 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control); | |
| 375 | |
| 376 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 377 Node* vtrue1 = graph()->NewNode(value->op(), object, context, frame_state, | |
| 378 effect, if_true1); | |
| 379 Node* etrue1 = vtrue1; | |
| 380 | |
| 381 Node* check2 = TestNotSmi(vtrue1); | |
| 382 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1); | |
| 383 | |
| 384 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 385 Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2); | |
| 386 | |
| 387 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 388 Node* vfalse2 = ChangeSmiToFloat64(vtrue1); | |
| 389 | |
| 390 if_true1 = graph()->NewNode(merge_op, if_true2, if_false2); | |
| 391 vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1); | |
| 392 | |
| 393 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 394 Node* vfalse1 = ChangeSmiToFloat64(object); | |
| 395 Node* efalse1 = effect; | |
| 396 | |
| 397 Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1); | |
| 398 Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1); | |
| 399 Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1); | |
| 400 | |
| 401 // Wire the new diamond into the graph, {JSToNumber} can still throw. | |
| 402 NodeProperties::ReplaceUses(value, phi1, ephi1, etrue1, etrue1); | |
| 403 | |
| 404 // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from | |
| 405 // the node and places it inside the diamond. Come up with a helper method! | |
| 406 for (Node* use : etrue1->uses()) { | |
| 407 if (use->opcode() == IrOpcode::kIfSuccess) { | |
| 408 use->ReplaceUses(merge1); | |
| 409 NodeProperties::ReplaceControlInput(branch2, use); | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 return Replace(phi1); | |
| 414 } | |
| 415 | |
| 416 Node* check = TestNotSmi(value); | 342 Node* check = TestNotSmi(value); |
| 417 Node* branch = | 343 Node* branch = |
| 418 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 344 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
| 419 | 345 |
| 420 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); | 346 Node* if_not_smi = graph()->NewNode(common()->IfTrue(), branch); |
| 421 | 347 |
| 422 Node* vnot_smi; | 348 Node* vnot_smi; |
| 423 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { | 349 if (NodeProperties::GetType(value)->Maybe(Type::Undefined())) { |
| 424 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, | 350 Node* check_undefined = graph()->NewNode(machine()->WordEqual(), value, |
| 425 jsgraph()->UndefinedConstant()); | 351 jsgraph()->UndefinedConstant()); |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 } | 707 } |
| 782 | 708 |
| 783 | 709 |
| 784 MachineOperatorBuilder* ChangeLowering::machine() const { | 710 MachineOperatorBuilder* ChangeLowering::machine() const { |
| 785 return jsgraph()->machine(); | 711 return jsgraph()->machine(); |
| 786 } | 712 } |
| 787 | 713 |
| 788 } // namespace compiler | 714 } // namespace compiler |
| 789 } // namespace internal | 715 } // namespace internal |
| 790 } // namespace v8 | 716 } // namespace v8 |
| OLD | NEW |