| 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-properties-inl.h" | 10 #include "src/compiler/node-properties-inl.h" |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); | 459 return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); |
| 460 } | 460 } |
| 461 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) | 461 // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types) |
| 462 return NoChange(); | 462 return NoChange(); |
| 463 } | 463 } |
| 464 | 464 |
| 465 | 465 |
| 466 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { | 466 Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { |
| 467 if (input->opcode() == IrOpcode::kJSToNumber) { | 467 if (input->opcode() == IrOpcode::kJSToNumber) { |
| 468 // Recursively try to reduce the input first. | 468 // Recursively try to reduce the input first. |
| 469 Reduction result = ReduceJSToNumberInput(input->InputAt(0)); | 469 Reduction result = ReduceJSToNumber(input); |
| 470 if (result.Changed()) { | 470 if (result.Changed()) return result; |
| 471 RelaxEffects(input); | |
| 472 return result; | |
| 473 } | |
| 474 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) | 471 return Changed(input); // JSToNumber(JSToNumber(x)) => JSToNumber(x) |
| 475 } | 472 } |
| 476 Type* input_type = NodeProperties::GetBounds(input).upper; | 473 Type* input_type = NodeProperties::GetBounds(input).upper; |
| 477 if (input_type->Is(Type::Number())) { | 474 if (input_type->Is(Type::Number())) { |
| 478 // JSToNumber(x:number) => x | 475 // JSToNumber(x:number) => x |
| 479 return Changed(input); | 476 return Changed(input); |
| 480 } | 477 } |
| 481 if (input_type->Is(Type::Undefined())) { | 478 if (input_type->Is(Type::Undefined())) { |
| 482 // JSToNumber(undefined) => #NaN | 479 // JSToNumber(undefined) => #NaN |
| 483 return ReplaceWith(jsgraph()->NaNConstant()); | 480 return ReplaceWith(jsgraph()->NaNConstant()); |
| 484 } | 481 } |
| 485 if (input_type->Is(Type::Null())) { | 482 if (input_type->Is(Type::Null())) { |
| 486 // JSToNumber(null) => #0 | 483 // JSToNumber(null) => #0 |
| 487 return ReplaceWith(jsgraph()->ZeroConstant()); | 484 return ReplaceWith(jsgraph()->ZeroConstant()); |
| 488 } | 485 } |
| 489 if (input_type->Is(Type::Boolean())) { | 486 if (input_type->Is(Type::Boolean())) { |
| 490 // JSToNumber(x:boolean) => BooleanToNumber(x) | 487 // JSToNumber(x:boolean) => BooleanToNumber(x) |
| 491 return ReplaceWith( | 488 return ReplaceWith( |
| 492 graph()->NewNode(simplified()->BooleanToNumber(), input)); | 489 graph()->NewNode(simplified()->BooleanToNumber(), input)); |
| 493 } | 490 } |
| 494 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) | 491 // TODO(turbofan): js-typed-lowering of ToNumber(x:string) |
| 495 return NoChange(); | 492 return NoChange(); |
| 496 } | 493 } |
| 497 | 494 |
| 498 | 495 |
| 496 Reduction JSTypedLowering::ReduceJSToNumber(Node* node) { |
| 497 // Try to reduce the input first. |
| 498 Node* const input = node->InputAt(0); |
| 499 Reduction reduction = ReduceJSToNumberInput(input); |
| 500 if (reduction.Changed()) { |
| 501 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
| 502 return reduction; |
| 503 } |
| 504 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| 505 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { |
| 506 Node* const context = node->InputAt(1); |
| 507 // JSToNumber(phi(x1,...,xn,control):primitive) |
| 508 // => phi(JSToNumber(x1),...,JSToNumber(xn),control):number |
| 509 RelaxEffects(node); |
| 510 int const input_count = input->InputCount() - 1; |
| 511 Node* const control = input->InputAt(input_count); |
| 512 DCHECK_LE(0, input_count); |
| 513 DCHECK(NodeProperties::IsControl(control)); |
| 514 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Number())); |
| 515 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Number())); |
| 516 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 517 for (int i = 0; i < input_count; ++i) { |
| 518 Node* value = input->InputAt(i); |
| 519 // Recursively try to reduce the value first. |
| 520 Reduction reduction = ReduceJSToNumberInput(value); |
| 521 if (reduction.Changed()) { |
| 522 value = reduction.replacement(); |
| 523 } else { |
| 524 value = graph()->NewNode(javascript()->ToNumber(), value, context, |
| 525 graph()->start(), graph()->start()); |
| 526 } |
| 527 if (i < node->InputCount()) { |
| 528 node->ReplaceInput(i, value); |
| 529 } else { |
| 530 node->AppendInput(graph()->zone(), value); |
| 531 } |
| 532 } |
| 533 if (input_count < node->InputCount()) { |
| 534 node->ReplaceInput(input_count, control); |
| 535 } else { |
| 536 node->AppendInput(graph()->zone(), control); |
| 537 } |
| 538 node->TrimInputCount(input_count + 1); |
| 539 return Changed(node); |
| 540 } |
| 541 return NoChange(); |
| 542 } |
| 543 |
| 544 |
| 499 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { | 545 Reduction JSTypedLowering::ReduceJSToStringInput(Node* input) { |
| 500 if (input->opcode() == IrOpcode::kJSToString) { | 546 if (input->opcode() == IrOpcode::kJSToString) { |
| 501 // Recursively try to reduce the input first. | 547 // Recursively try to reduce the input first. |
| 502 Reduction result = ReduceJSToStringInput(input->InputAt(0)); | 548 Reduction result = ReduceJSToStringInput(input->InputAt(0)); |
| 503 if (result.Changed()) { | 549 if (result.Changed()) { |
| 504 RelaxEffects(input); | 550 RelaxEffects(input); |
| 505 return result; | 551 return result; |
| 506 } | 552 } |
| 507 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) | 553 return Changed(input); // JSToString(JSToString(x)) => JSToString(x) |
| 508 } | 554 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { | 621 Reduction JSTypedLowering::ReduceJSToBoolean(Node* node) { |
| 576 // Try to reduce the input first. | 622 // Try to reduce the input first. |
| 577 Node* const input = node->InputAt(0); | 623 Node* const input = node->InputAt(0); |
| 578 Reduction reduction = ReduceJSToBooleanInput(input); | 624 Reduction reduction = ReduceJSToBooleanInput(input); |
| 579 if (reduction.Changed()) { | 625 if (reduction.Changed()) { |
| 580 NodeProperties::ReplaceWithValue(node, reduction.replacement()); | 626 NodeProperties::ReplaceWithValue(node, reduction.replacement()); |
| 581 return reduction; | 627 return reduction; |
| 582 } | 628 } |
| 583 Type* const input_type = NodeProperties::GetBounds(input).upper; | 629 Type* const input_type = NodeProperties::GetBounds(input).upper; |
| 584 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { | 630 if (input->opcode() == IrOpcode::kPhi && input_type->Is(Type::Primitive())) { |
| 631 Node* const context = node->InputAt(1); |
| 585 // JSToBoolean(phi(x1,...,xn,control):primitive) | 632 // JSToBoolean(phi(x1,...,xn,control):primitive) |
| 586 // => phi(JSToBoolean(x1),...,JSToBoolean(xn),control):boolean | 633 // => phi(JSToBoolean(x1),...,JSToBoolean(xn),control):boolean |
| 587 RelaxEffects(node); | 634 RelaxEffects(node); |
| 588 int const input_count = input->InputCount() - 1; | 635 int const input_count = input->InputCount() - 1; |
| 589 Node* const control = input->InputAt(input_count); | 636 Node* const control = input->InputAt(input_count); |
| 590 DCHECK_LE(0, input_count); | 637 DCHECK_LE(0, input_count); |
| 591 DCHECK(NodeProperties::IsControl(control)); | 638 DCHECK(NodeProperties::IsControl(control)); |
| 592 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); | 639 DCHECK(NodeProperties::GetBounds(node).upper->Is(Type::Boolean())); |
| 593 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); | 640 DCHECK(!NodeProperties::GetBounds(input).upper->Is(Type::Boolean())); |
| 594 node->set_op(common()->Phi(kMachAnyTagged, input_count)); | 641 node->set_op(common()->Phi(kMachAnyTagged, input_count)); |
| 595 for (int i = 0; i < input_count; ++i) { | 642 for (int i = 0; i < input_count; ++i) { |
| 596 Node* value = input->InputAt(i); | 643 Node* value = input->InputAt(i); |
| 597 // Recursively try to reduce the value first. | 644 // Recursively try to reduce the value first. |
| 598 Reduction reduction = ReduceJSToBooleanInput(value); | 645 Reduction reduction = ReduceJSToBooleanInput(value); |
| 599 if (reduction.Changed()) { | 646 if (reduction.Changed()) { |
| 600 value = reduction.replacement(); | 647 value = reduction.replacement(); |
| 601 } else { | 648 } else { |
| 602 value = graph()->NewNode(javascript()->ToBoolean(), value, | 649 value = graph()->NewNode(javascript()->ToBoolean(), value, context, |
| 603 jsgraph()->ZeroConstant(), graph()->start(), | 650 graph()->start(), graph()->start()); |
| 604 graph()->start()); | |
| 605 } | 651 } |
| 606 if (i < node->InputCount()) { | 652 if (i < node->InputCount()) { |
| 607 node->ReplaceInput(i, value); | 653 node->ReplaceInput(i, value); |
| 608 } else { | 654 } else { |
| 609 node->AppendInput(graph()->zone(), value); | 655 node->AppendInput(graph()->zone(), value); |
| 610 } | 656 } |
| 611 } | 657 } |
| 612 if (input_count < node->InputCount()) { | 658 if (input_count < node->InputCount()) { |
| 613 node->ReplaceInput(input_count, control); | 659 node->ReplaceInput(input_count, control); |
| 614 } else { | 660 } else { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 node->set_op(javascript()->ToBoolean()); | 808 node->set_op(javascript()->ToBoolean()); |
| 763 NodeProperties::ReplaceWithValue(node, value, node); | 809 NodeProperties::ReplaceWithValue(node, value, node); |
| 764 // Note: ReplaceUses() smashes all uses, so smash it back here. | 810 // Note: ReplaceUses() smashes all uses, so smash it back here. |
| 765 value->ReplaceInput(0, node); | 811 value->ReplaceInput(0, node); |
| 766 return Changed(node); | 812 return Changed(node); |
| 767 } | 813 } |
| 768 } | 814 } |
| 769 case IrOpcode::kJSToBoolean: | 815 case IrOpcode::kJSToBoolean: |
| 770 return ReduceJSToBoolean(node); | 816 return ReduceJSToBoolean(node); |
| 771 case IrOpcode::kJSToNumber: | 817 case IrOpcode::kJSToNumber: |
| 772 return ReplaceWithReduction(node, | 818 return ReduceJSToNumber(node); |
| 773 ReduceJSToNumberInput(node->InputAt(0))); | |
| 774 case IrOpcode::kJSToString: | 819 case IrOpcode::kJSToString: |
| 775 return ReplaceWithReduction(node, | 820 return ReplaceWithReduction(node, |
| 776 ReduceJSToStringInput(node->InputAt(0))); | 821 ReduceJSToStringInput(node->InputAt(0))); |
| 777 case IrOpcode::kJSLoadProperty: | 822 case IrOpcode::kJSLoadProperty: |
| 778 return ReduceJSLoadProperty(node); | 823 return ReduceJSLoadProperty(node); |
| 779 case IrOpcode::kJSStoreProperty: | 824 case IrOpcode::kJSStoreProperty: |
| 780 return ReduceJSStoreProperty(node); | 825 return ReduceJSStoreProperty(node); |
| 781 case IrOpcode::kJSCallFunction: | 826 case IrOpcode::kJSCallFunction: |
| 782 return JSBuiltinReducer(jsgraph()).Reduce(node); | 827 return JSBuiltinReducer(jsgraph()).Reduce(node); |
| 783 default: | 828 default: |
| 784 break; | 829 break; |
| 785 } | 830 } |
| 786 return NoChange(); | 831 return NoChange(); |
| 787 } | 832 } |
| 788 | 833 |
| 789 } // namespace compiler | 834 } // namespace compiler |
| 790 } // namespace internal | 835 } // namespace internal |
| 791 } // namespace v8 | 836 } // namespace v8 |
| OLD | NEW |