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 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 | 600 |
601 // Push global object (receiver). | 601 // Push global object (receiver). |
602 __ ldr(r0, CodeGenerator::GlobalObject()); | 602 __ ldr(r0, CodeGenerator::GlobalObject()); |
603 __ push(r0); | 603 __ push(r0); |
604 // Push the arguments ("left-to-right") on the stack. | 604 // Push the arguments ("left-to-right") on the stack. |
605 ZoneList<Expression*>* args = node->arguments(); | 605 ZoneList<Expression*>* args = node->arguments(); |
606 int arg_count = args->length(); | 606 int arg_count = args->length(); |
607 for (int i = 0; i < arg_count; i++) { | 607 for (int i = 0; i < arg_count; i++) { |
608 Visit(args->at(i)); | 608 Visit(args->at(i)); |
609 ASSERT(args->at(i)->location().is_value()); | 609 ASSERT(args->at(i)->location().is_value()); |
610 // If location is temporary, it is already on the stack, | 610 // If location is value, it is already on the stack, |
611 // so nothing to do here. | 611 // so nothing to do here. |
612 } | 612 } |
613 | 613 |
614 // Call the construct call builtin that handles allocation and | 614 // Call the construct call builtin that handles allocation and |
615 // constructor invocation. | 615 // constructor invocation. |
616 SetSourcePosition(node->position()); | 616 SetSourcePosition(node->position()); |
617 | 617 |
618 // Load function, arg_count into r1 and r0. | 618 // Load function, arg_count into r1 and r0. |
619 __ mov(r0, Operand(arg_count)); | 619 __ mov(r0, Operand(arg_count)); |
620 // Function is in esp[arg_count + 1]. | 620 // Function is in esp[arg_count + 1]. |
(...skipping 20 matching lines...) Expand all Loading... |
641 Visit(args->at(i)); | 641 Visit(args->at(i)); |
642 ASSERT(args->at(i)->location().is_value()); | 642 ASSERT(args->at(i)->location().is_value()); |
643 } | 643 } |
644 | 644 |
645 __ CallRuntime(function, arg_count); | 645 __ CallRuntime(function, arg_count); |
646 Move(expr->location(), r0); | 646 Move(expr->location(), r0); |
647 } | 647 } |
648 | 648 |
649 | 649 |
650 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 650 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
651 // Compile a short-circuited boolean or operation in a non-test | 651 switch (expr->op()) { |
652 // context. | 652 case Token::COMMA: |
653 ASSERT(expr->op() == Token::OR); | 653 ASSERT(expr->left()->location().is_effect()); |
| 654 ASSERT_EQ(expr->right()->location().type(), expr->location().type()); |
| 655 Visit(expr->left()); |
| 656 Visit(expr->right()); |
| 657 break; |
| 658 |
| 659 case Token::OR: |
| 660 case Token::AND: |
| 661 EmitLogicalOperation(expr); |
| 662 break; |
| 663 |
| 664 case Token::ADD: |
| 665 case Token::SUB: |
| 666 case Token::DIV: |
| 667 case Token::MOD: |
| 668 case Token::MUL: |
| 669 case Token::BIT_OR: |
| 670 case Token::BIT_AND: |
| 671 case Token::BIT_XOR: |
| 672 case Token::SHL: |
| 673 case Token::SHR: |
| 674 case Token::SAR: { |
| 675 ASSERT(expr->left()->location().is_value()); |
| 676 ASSERT(expr->right()->location().is_value()); |
| 677 |
| 678 Visit(expr->left()); |
| 679 Visit(expr->right()); |
| 680 __ pop(r0); |
| 681 __ pop(r1); |
| 682 GenericBinaryOpStub stub(expr->op(), |
| 683 NO_OVERWRITE); |
| 684 __ CallStub(&stub); |
| 685 Move(expr->location(), r0); |
| 686 |
| 687 break; |
| 688 } |
| 689 default: |
| 690 UNREACHABLE(); |
| 691 } |
| 692 } |
| 693 |
| 694 |
| 695 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| 696 // Compile a short-circuited boolean operation in a non-test context. |
| 697 |
654 // Compile (e0 || e1) as if it were | 698 // Compile (e0 || e1) as if it were |
655 // (let (temp = e0) temp ? temp : e1). | 699 // (let (temp = e0) temp ? temp : e1). |
| 700 // Compile (e0 && e1) as if it were |
| 701 // (let (temp = e0) !temp ? temp : e1). |
656 | 702 |
657 Label done; | 703 Label done; |
658 Location destination = expr->location(); | 704 Location destination = expr->location(); |
659 Expression* left = expr->left(); | 705 Expression* left = expr->left(); |
660 Expression* right = expr->right(); | 706 Expression* right = expr->right(); |
661 | 707 |
662 // Call the runtime to find the boolean value of the left-hand | 708 // Call the runtime to find the boolean value of the left-hand |
663 // subexpression. Duplicate the value if it may be needed as the final | 709 // subexpression. Duplicate the value if it may be needed as the final |
664 // result. | 710 // result. |
665 if (left->AsLiteral() != NULL) { | 711 if (left->AsLiteral() != NULL) { |
666 __ mov(r0, Operand(left->AsLiteral()->handle())); | 712 __ mov(r0, Operand(left->AsLiteral()->handle())); |
667 __ push(r0); | 713 __ push(r0); |
668 if (destination.is_value()) __ push(r0); | 714 if (destination.is_value()) __ push(r0); |
669 } else { | 715 } else { |
670 Visit(left); | 716 Visit(left); |
671 ASSERT(left->location().is_value()); | 717 ASSERT(left->location().is_value()); |
672 if (destination.is_value()) { | 718 if (destination.is_value()) { |
673 __ ldr(r0, MemOperand(sp)); | 719 __ ldr(r0, MemOperand(sp)); |
674 __ push(r0); | 720 __ push(r0); |
675 } | 721 } |
676 } | 722 } |
677 // The left-hand value is in on top of the stack. It is duplicated on the | 723 // The left-hand value is in on top of the stack. It is duplicated on the |
678 // stack iff the destination location is temporary. | 724 // stack iff the destination location is value. |
679 __ CallRuntime(Runtime::kToBool, 1); | 725 __ CallRuntime(Runtime::kToBool, 1); |
680 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 726 if (expr->op() == Token::OR) { |
| 727 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 728 } else { |
| 729 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 730 } |
681 __ cmp(r0, ip); | 731 __ cmp(r0, ip); |
682 __ b(eq, &done); | 732 __ b(eq, &done); |
683 | 733 |
684 // Discard the left-hand value if present on the stack. | 734 // Discard the left-hand value if present on the stack. |
685 if (destination.is_value()) __ pop(); | 735 if (destination.is_value()) __ pop(); |
686 // Save or discard the right-hand value as needed. | 736 // Save or discard the right-hand value as needed. |
687 if (right->AsLiteral() != NULL) { | 737 if (right->AsLiteral() != NULL) { |
688 Move(destination, right->AsLiteral()); | 738 Move(destination, right->AsLiteral()); |
689 } else { | 739 } else { |
690 Visit(right); | 740 Visit(right); |
691 Move(destination, right->location()); | 741 Move(destination, right->location()); |
692 } | 742 } |
693 | 743 |
694 __ bind(&done); | 744 __ bind(&done); |
695 } | 745 } |
696 | 746 |
697 } } // namespace v8::internal | 747 } } // namespace v8::internal |
OLD | NEW |