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 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 | 583 |
584 // Push global object (receiver). | 584 // Push global object (receiver). |
585 __ push(CodeGenerator::GlobalObject()); | 585 __ push(CodeGenerator::GlobalObject()); |
586 | 586 |
587 // Push the arguments ("left-to-right") on the stack. | 587 // Push the arguments ("left-to-right") on the stack. |
588 ZoneList<Expression*>* args = node->arguments(); | 588 ZoneList<Expression*>* args = node->arguments(); |
589 int arg_count = args->length(); | 589 int arg_count = args->length(); |
590 for (int i = 0; i < arg_count; i++) { | 590 for (int i = 0; i < arg_count; i++) { |
591 Visit(args->at(i)); | 591 Visit(args->at(i)); |
592 ASSERT(args->at(i)->location().is_value()); | 592 ASSERT(args->at(i)->location().is_value()); |
593 // If location is temporary, it is already on the stack, | 593 // If location is value, it is already on the stack, |
594 // so nothing to do here. | 594 // so nothing to do here. |
595 } | 595 } |
596 | 596 |
597 // Call the construct call builtin that handles allocation and | 597 // Call the construct call builtin that handles allocation and |
598 // constructor invocation. | 598 // constructor invocation. |
599 SetSourcePosition(node->position()); | 599 SetSourcePosition(node->position()); |
600 | 600 |
601 // Load function, arg_count into edi and eax. | 601 // Load function, arg_count into edi and eax. |
602 __ Set(eax, Immediate(arg_count)); | 602 __ Set(eax, Immediate(arg_count)); |
603 // Function is in esp[arg_count + 1]. | 603 // Function is in esp[arg_count + 1]. |
(...skipping 20 matching lines...) Expand all Loading... |
624 Visit(args->at(i)); | 624 Visit(args->at(i)); |
625 ASSERT(args->at(i)->location().is_value()); | 625 ASSERT(args->at(i)->location().is_value()); |
626 } | 626 } |
627 | 627 |
628 __ CallRuntime(function, arg_count); | 628 __ CallRuntime(function, arg_count); |
629 Move(expr->location(), eax); | 629 Move(expr->location(), eax); |
630 } | 630 } |
631 | 631 |
632 | 632 |
633 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 633 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
634 // Compile a short-circuited boolean or operation in a non-test | 634 switch (expr->op()) { |
635 // context. | 635 case Token::COMMA: |
636 ASSERT(expr->op() == Token::OR); | 636 ASSERT(expr->left()->location().is_effect()); |
637 // Compile (e0 || e1) as if it were | 637 ASSERT_EQ(expr->right()->location().type(), expr->location().type()); |
638 // (let (temp = e0) temp ? temp : e1). | 638 Visit(expr->left()); |
| 639 Visit(expr->right()); |
| 640 break; |
| 641 |
| 642 case Token::OR: |
| 643 case Token::AND: |
| 644 EmitLogicalOperation(expr); |
| 645 break; |
| 646 |
| 647 case Token::ADD: |
| 648 case Token::SUB: |
| 649 case Token::DIV: |
| 650 case Token::MOD: |
| 651 case Token::MUL: |
| 652 case Token::BIT_OR: |
| 653 case Token::BIT_AND: |
| 654 case Token::BIT_XOR: |
| 655 case Token::SHL: |
| 656 case Token::SHR: |
| 657 case Token::SAR: { |
| 658 ASSERT(expr->left()->location().is_value()); |
| 659 ASSERT(expr->right()->location().is_value()); |
| 660 |
| 661 Visit(expr->left()); |
| 662 Visit(expr->right()); |
| 663 GenericBinaryOpStub stub(expr->op(), |
| 664 NO_OVERWRITE, |
| 665 NO_GENERIC_BINARY_FLAGS); |
| 666 __ CallStub(&stub); |
| 667 Move(expr->location(), eax); |
| 668 |
| 669 break; |
| 670 } |
| 671 default: |
| 672 UNREACHABLE(); |
| 673 } |
| 674 } |
| 675 |
| 676 |
| 677 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| 678 // Compile a short-circuited boolean operation in a non-test context. |
| 679 |
| 680 // Compile (e0 || e1) or (e0 && e1) as if it were |
| 681 // (let (temp = e0) temp [or !temp, for &&] ? temp : e1). |
639 | 682 |
640 Label eval_right, done; | 683 Label eval_right, done; |
| 684 Label *left_true, *left_false; // Where to branch to if lhs has that value. |
| 685 if (expr->op() == Token::OR) { |
| 686 left_true = &done; |
| 687 left_false = &eval_right; |
| 688 } else { |
| 689 left_true = &eval_right; |
| 690 left_false = &done; |
| 691 } |
641 Location destination = expr->location(); | 692 Location destination = expr->location(); |
642 Expression* left = expr->left(); | 693 Expression* left = expr->left(); |
643 Expression* right = expr->right(); | 694 Expression* right = expr->right(); |
644 | 695 |
645 // Use the shared ToBoolean stub to find the boolean value of the | 696 // Use the shared ToBoolean stub to find the boolean value of the |
646 // left-hand subexpression. Load the value into eax to perform some | 697 // left-hand subexpression. Load the value into eax to perform some |
647 // inlined checks assumed by the stub. | 698 // inlined checks assumed by the stub. |
648 | 699 |
649 // Compile the left-hand value into eax. Put it on the stack if we may | 700 // Compile the left-hand value into eax. Put it on the stack if we may |
650 // need it as the value of the whole expression. | 701 // need it as the value of the whole expression. |
(...skipping 12 matching lines...) Expand all Loading... |
663 __ pop(eax); | 714 __ pop(eax); |
664 break; | 715 break; |
665 case Location::VALUE: | 716 case Location::VALUE: |
666 // Copy the left-hand value into eax because we may need it as the | 717 // Copy the left-hand value into eax because we may need it as the |
667 // final result. | 718 // final result. |
668 __ mov(eax, Operand(esp, 0)); | 719 __ mov(eax, Operand(esp, 0)); |
669 break; | 720 break; |
670 } | 721 } |
671 } | 722 } |
672 // The left-hand value is in eax. It is also on the stack iff the | 723 // The left-hand value is in eax. It is also on the stack iff the |
673 // destination location is temporary. | 724 // destination location is value. |
674 | 725 |
675 // Perform fast checks assumed by the stub. | 726 // Perform fast checks assumed by the stub. |
676 __ cmp(eax, Factory::undefined_value()); // The undefined value is false. | 727 __ cmp(eax, Factory::undefined_value()); // The undefined value is false. |
677 __ j(equal, &eval_right); | 728 __ j(equal, left_false); |
678 __ cmp(eax, Factory::true_value()); // True is true. | 729 __ cmp(eax, Factory::true_value()); // True is true. |
679 __ j(equal, &done); | 730 __ j(equal, left_true); |
680 __ cmp(eax, Factory::false_value()); // False is false. | 731 __ cmp(eax, Factory::false_value()); // False is false. |
681 __ j(equal, &eval_right); | 732 __ j(equal, left_false); |
682 ASSERT(kSmiTag == 0); | 733 ASSERT(kSmiTag == 0); |
683 __ test(eax, Operand(eax)); // The smi zero is false. | 734 __ test(eax, Operand(eax)); // The smi zero is false. |
684 __ j(zero, &eval_right); | 735 __ j(zero, left_false); |
685 __ test(eax, Immediate(kSmiTagMask)); // All other smis are true. | 736 __ test(eax, Immediate(kSmiTagMask)); // All other smis are true. |
686 __ j(zero, &done); | 737 __ j(zero, left_true); |
687 | 738 |
688 // Call the stub for all other cases. | 739 // Call the stub for all other cases. |
689 __ push(eax); | 740 __ push(eax); |
690 ToBooleanStub stub; | 741 ToBooleanStub stub; |
691 __ CallStub(&stub); | 742 __ CallStub(&stub); |
692 __ test(eax, Operand(eax)); // The stub returns nonzero for true. | 743 __ test(eax, Operand(eax)); // The stub returns nonzero for true. |
693 __ j(not_zero, &done); | 744 if (expr->op() == Token::OR) { |
| 745 __ j(not_zero, &done); |
| 746 } else { |
| 747 __ j(zero, &done); |
| 748 } |
694 | 749 |
695 __ bind(&eval_right); | 750 __ bind(&eval_right); |
696 // Discard the left-hand value if present on the stack. | 751 // Discard the left-hand value if present on the stack. |
697 if (destination.is_value()) { | 752 if (destination.is_value()) { |
698 __ add(Operand(esp), Immediate(kPointerSize)); | 753 __ add(Operand(esp), Immediate(kPointerSize)); |
699 } | 754 } |
700 // Save or discard the right-hand value as needed. | 755 // Save or discard the right-hand value as needed. |
701 if (right->AsLiteral() != NULL) { | 756 if (right->AsLiteral() != NULL) { |
702 Move(destination, right->AsLiteral()); | 757 Move(destination, right->AsLiteral()); |
703 } else { | 758 } else { |
704 Visit(right); | 759 Visit(right); |
705 Move(destination, right->location()); | 760 Move(destination, right->location()); |
706 } | 761 } |
707 | 762 |
708 __ bind(&done); | 763 __ bind(&done); |
709 } | 764 } |
710 | 765 |
711 | 766 |
712 } } // namespace v8::internal | 767 } } // namespace v8::internal |
OLD | NEW |