| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 | 586 |
| 587 | 587 |
| 588 void FastCodeGenerator::VisitCallNew(CallNew* node) { | 588 void FastCodeGenerator::VisitCallNew(CallNew* node) { |
| 589 Comment cmnt(masm_, "[ CallNew"); | 589 Comment cmnt(masm_, "[ CallNew"); |
| 590 // According to ECMA-262, section 11.2.2, page 44, the function | 590 // According to ECMA-262, section 11.2.2, page 44, the function |
| 591 // expression in new calls must be evaluated before the | 591 // expression in new calls must be evaluated before the |
| 592 // arguments. | 592 // arguments. |
| 593 // Push function on the stack. | 593 // Push function on the stack. |
| 594 Visit(node->expression()); | 594 Visit(node->expression()); |
| 595 ASSERT(node->expression()->location().is_value()); | 595 ASSERT(node->expression()->location().is_value()); |
| 596 // If location is temporary, already on the stack, | 596 // If location is value, already on the stack, |
| 597 | 597 |
| 598 // Push global object (receiver). | 598 // Push global object (receiver). |
| 599 __ push(CodeGenerator::GlobalObject()); | 599 __ push(CodeGenerator::GlobalObject()); |
| 600 | 600 |
| 601 // Push the arguments ("left-to-right") on the stack. | 601 // Push the arguments ("left-to-right") on the stack. |
| 602 ZoneList<Expression*>* args = node->arguments(); | 602 ZoneList<Expression*>* args = node->arguments(); |
| 603 int arg_count = args->length(); | 603 int arg_count = args->length(); |
| 604 for (int i = 0; i < arg_count; i++) { | 604 for (int i = 0; i < arg_count; i++) { |
| 605 Visit(args->at(i)); | 605 Visit(args->at(i)); |
| 606 ASSERT(args->at(i)->location().is_value()); | 606 ASSERT(args->at(i)->location().is_value()); |
| 607 // If location is temporary, it is already on the stack, | 607 // If location is value, it is already on the stack, |
| 608 // so nothing to do here. | 608 // so nothing to do here. |
| 609 } | 609 } |
| 610 | 610 |
| 611 // Call the construct call builtin that handles allocation and | 611 // Call the construct call builtin that handles allocation and |
| 612 // constructor invocation. | 612 // constructor invocation. |
| 613 SetSourcePosition(node->position()); | 613 SetSourcePosition(node->position()); |
| 614 | 614 |
| 615 // Load function, arg_count into rdi and rax. | 615 // Load function, arg_count into rdi and rax. |
| 616 __ Set(rax, arg_count); | 616 __ Set(rax, arg_count); |
| 617 // Function is in rsp[arg_count + 1]. | 617 // Function is in rsp[arg_count + 1]. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 638 Visit(args->at(i)); | 638 Visit(args->at(i)); |
| 639 ASSERT(args->at(i)->location().is_value()); | 639 ASSERT(args->at(i)->location().is_value()); |
| 640 } | 640 } |
| 641 | 641 |
| 642 __ CallRuntime(function, arg_count); | 642 __ CallRuntime(function, arg_count); |
| 643 Move(expr->location(), rax); | 643 Move(expr->location(), rax); |
| 644 } | 644 } |
| 645 | 645 |
| 646 | 646 |
| 647 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 647 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 648 // Compile a short-circuited boolean or operation in a non-test | 648 switch (expr->op()) { |
| 649 // context. | 649 case Token::COMMA: |
| 650 ASSERT(expr->op() == Token::OR); | 650 ASSERT(expr->left()->location().is_effect()); |
| 651 ASSERT_EQ(expr->right()->location().type(), expr->location().type()); |
| 652 Visit(expr->left()); |
| 653 Visit(expr->right()); |
| 654 break; |
| 655 |
| 656 case Token::OR: |
| 657 case Token::AND: |
| 658 EmitLogicalOperation(expr); |
| 659 break; |
| 660 |
| 661 case Token::ADD: |
| 662 case Token::SUB: |
| 663 case Token::DIV: |
| 664 case Token::MOD: |
| 665 case Token::MUL: |
| 666 case Token::BIT_OR: |
| 667 case Token::BIT_AND: |
| 668 case Token::BIT_XOR: |
| 669 case Token::SHL: |
| 670 case Token::SHR: |
| 671 case Token::SAR: { |
| 672 ASSERT(expr->left()->location().is_value()); |
| 673 ASSERT(expr->right()->location().is_value()); |
| 674 |
| 675 Visit(expr->left()); |
| 676 Visit(expr->right()); |
| 677 GenericBinaryOpStub stub(expr->op(), |
| 678 NO_OVERWRITE, |
| 679 NO_GENERIC_BINARY_FLAGS); |
| 680 __ CallStub(&stub); |
| 681 Move(expr->location(), kReturnRegister); |
| 682 |
| 683 break; |
| 684 } |
| 685 default: |
| 686 UNREACHABLE(); |
| 687 } |
| 688 } |
| 689 |
| 690 |
| 691 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| 692 // Compile a short-circuited boolean operation in a non-test context. |
| 693 |
| 651 // Compile (e0 || e1) as if it were | 694 // Compile (e0 || e1) as if it were |
| 652 // (let (temp = e0) temp ? temp : e1). | 695 // (let (temp = e0) temp ? temp : e1). |
| 696 // Compile (e0 && e1) as if it were |
| 697 // (let (temp = e0) !temp ? temp : e1). |
| 653 | 698 |
| 654 Label eval_right, done; | 699 Label eval_right, done; |
| 700 Label *left_true, *left_false; // Where to branch to if lhs has that value. |
| 701 if (expr->op() == Token::OR) { |
| 702 left_true = &done; |
| 703 left_false = &eval_right; |
| 704 } else { |
| 705 left_true = &eval_right; |
| 706 left_false = &done; |
| 707 } |
| 655 Location destination = expr->location(); | 708 Location destination = expr->location(); |
| 656 Expression* left = expr->left(); | 709 Expression* left = expr->left(); |
| 657 Expression* right = expr->right(); | 710 Expression* right = expr->right(); |
| 658 | 711 |
| 659 // Use the shared ToBoolean stub to find the boolean value of the | 712 // Use the shared ToBoolean stub to find the boolean value of the |
| 660 // left-hand subexpression. Load the value into rax to perform some | 713 // left-hand subexpression. Load the value into rax to perform some |
| 661 // inlined checks assumed by the stub. | 714 // inlined checks assumed by the stub. |
| 662 | 715 |
| 663 // Compile the left-hand value into rax. Put it on the stack if we may | 716 // Compile the left-hand value into rax. Put it on the stack if we may |
| 664 // need it as the value of the whole expression. | 717 // need it as the value of the whole expression. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 677 __ pop(rax); | 730 __ pop(rax); |
| 678 break; | 731 break; |
| 679 case Location::VALUE: | 732 case Location::VALUE: |
| 680 // Copy the left-hand value into rax because we may need it as the | 733 // Copy the left-hand value into rax because we may need it as the |
| 681 // final result. | 734 // final result. |
| 682 __ movq(rax, Operand(rsp, 0)); | 735 __ movq(rax, Operand(rsp, 0)); |
| 683 break; | 736 break; |
| 684 } | 737 } |
| 685 } | 738 } |
| 686 // The left-hand value is in rax. It is also on the stack iff the | 739 // The left-hand value is in rax. It is also on the stack iff the |
| 687 // destination location is temporary. | 740 // destination location is value. |
| 688 | 741 |
| 689 // Perform fast checks assumed by the stub. | 742 // Perform fast checks assumed by the stub. |
| 690 // The undefined value is false. | 743 // The undefined value is false. |
| 691 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 744 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 692 __ j(equal, &eval_right); | 745 __ j(equal, left_false); |
| 693 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true. | 746 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true. |
| 694 __ j(equal, &done); | 747 __ j(equal, left_true); |
| 695 __ CompareRoot(rax, Heap::kFalseValueRootIndex); // False is false. | 748 __ CompareRoot(rax, Heap::kFalseValueRootIndex); // False is false. |
| 696 __ j(equal, &eval_right); | 749 __ j(equal, left_false); |
| 697 ASSERT(kSmiTag == 0); | 750 ASSERT(kSmiTag == 0); |
| 698 __ SmiCompare(rax, Smi::FromInt(0)); // The smi zero is false. | 751 __ SmiCompare(rax, Smi::FromInt(0)); // The smi zero is false. |
| 699 __ j(equal, &eval_right); | 752 __ j(equal, left_false); |
| 700 Condition is_smi = masm_->CheckSmi(rax); // All other smis are true. | 753 Condition is_smi = masm_->CheckSmi(rax); // All other smis are true. |
| 701 __ j(is_smi, &done); | 754 __ j(is_smi, left_true); |
| 702 | 755 |
| 703 // Call the stub for all other cases. | 756 // Call the stub for all other cases. |
| 704 __ push(rax); | 757 __ push(rax); |
| 705 ToBooleanStub stub; | 758 ToBooleanStub stub; |
| 706 __ CallStub(&stub); | 759 __ CallStub(&stub); |
| 707 __ testq(rax, rax); // The stub returns nonzero for true. | 760 __ testq(rax, rax); // The stub returns nonzero for true. |
| 708 __ j(not_zero, &done); | 761 if (expr->op() == Token::OR) { |
| 762 __ j(not_zero, &done); |
| 763 } else { |
| 764 __ j(zero, &done); |
| 765 } |
| 709 | 766 |
| 710 __ bind(&eval_right); | 767 __ bind(&eval_right); |
| 711 // Discard the left-hand value if present on the stack. | 768 // Discard the left-hand value if present on the stack. |
| 712 if (destination.is_value()) { | 769 if (destination.is_value()) { |
| 713 __ addq(rsp, Immediate(kPointerSize)); | 770 __ addq(rsp, Immediate(kPointerSize)); |
| 714 } | 771 } |
| 715 // Save or discard the right-hand value as needed. | 772 // Save or discard the right-hand value as needed. |
| 716 if (right->AsLiteral() != NULL) { | 773 if (right->AsLiteral() != NULL) { |
| 717 Move(destination, right->AsLiteral()); | 774 Move(destination, right->AsLiteral()); |
| 718 } else { | 775 } else { |
| 719 Visit(right); | 776 Visit(right); |
| 720 Move(destination, right->location()); | 777 Move(destination, right->location()); |
| 721 } | 778 } |
| 722 | 779 |
| 723 __ bind(&done); | 780 __ bind(&done); |
| 724 } | 781 } |
| 725 | 782 |
| 726 | 783 |
| 727 } } // namespace v8::internal | 784 } } // namespace v8::internal |
| OLD | NEW |