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 |