Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: src/codegen-arm.cc

Issue 20408: Experimental: more stuff to get ARM to work. Stubbed out frame merge... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 case Token::SHR: 661 case Token::SHR:
662 case Token::SAR: { 662 case Token::SAR: {
663 frame_->EmitPop(r0); // r0 : y 663 frame_->EmitPop(r0); // r0 : y
664 frame_->EmitPop(r1); // r1 : x 664 frame_->EmitPop(r1); // r1 : x
665 GenericBinaryOpStub stub(op); 665 GenericBinaryOpStub stub(op);
666 frame_->CallStub(&stub, 0); 666 frame_->CallStub(&stub, 0);
667 break; 667 break;
668 } 668 }
669 669
670 case Token::DIV: { 670 case Token::DIV: {
671 __ mov(r0, Operand(1)); 671 Result arg_count = allocator_->Allocate(r0);
672 frame_->InvokeBuiltin(Builtins::DIV, CALL_JS, 2); 672 ASSERT(arg_count.is_valid());
673 __ mov(arg_count.reg(), Operand(1));
674 frame_->InvokeBuiltin(Builtins::DIV, CALL_JS, &arg_count, 2);
673 break; 675 break;
674 } 676 }
675 677
676 case Token::MOD: { 678 case Token::MOD: {
677 __ mov(r0, Operand(1)); 679 Result arg_count = allocator_->Allocate(r0);
678 frame_->InvokeBuiltin(Builtins::MOD, CALL_JS, 2); 680 ASSERT(arg_count.is_valid());
681 __ mov(arg_count.reg(), Operand(1));
682 frame_->InvokeBuiltin(Builtins::MOD, CALL_JS, &arg_count, 2);
679 break; 683 break;
680 } 684 }
681 685
682 case Token::COMMA: 686 case Token::COMMA:
683 frame_->EmitPop(r0); 687 frame_->EmitPop(r0);
684 // simply discard left value 688 // simply discard left value
685 frame_->Drop(); 689 frame_->Drop();
686 break; 690 break;
687 691
688 default: 692 default:
689 // Other cases should have been handled before this point. 693 // Other cases should have been handled before this point.
690 UNREACHABLE(); 694 UNREACHABLE();
691 break; 695 break;
692 } 696 }
693 } 697 }
694 698
695 699
696 class DeferredInlinedSmiOperation: public DeferredCode { 700 class DeferredInlineSmiOperation: public DeferredCode {
697 public: 701 public:
698 DeferredInlinedSmiOperation(CodeGenerator* generator, Token::Value op, 702 DeferredInlineSmiOperation(CodeGenerator* generator,
699 int value, bool reversed) : 703 Token::Value op,
700 DeferredCode(generator), op_(op), value_(value), reversed_(reversed) { 704 int value,
705 bool reversed)
706 : DeferredCode(generator),
707 op_(op),
708 value_(value),
709 reversed_(reversed) {
701 set_comment("[ DeferredInlinedSmiOperation"); 710 set_comment("[ DeferredInlinedSmiOperation");
702 } 711 }
703 712
704 virtual void Generate() { 713 virtual void Generate();
705 switch (op_) {
706 case Token::ADD: {
707 if (reversed_) {
708 // revert optimistic add
709 __ sub(r0, r0, Operand(Smi::FromInt(value_)));
710 __ mov(r1, Operand(Smi::FromInt(value_))); // x
711 } else {
712 // revert optimistic add
713 __ sub(r1, r0, Operand(Smi::FromInt(value_)));
714 __ mov(r0, Operand(Smi::FromInt(value_)));
715 }
716 break;
717 }
718
719 case Token::SUB: {
720 if (reversed_) {
721 // revert optimistic sub
722 __ rsb(r0, r0, Operand(Smi::FromInt(value_)));
723 __ mov(r1, Operand(Smi::FromInt(value_)));
724 } else {
725 __ add(r1, r0, Operand(Smi::FromInt(value_)));
726 __ mov(r0, Operand(Smi::FromInt(value_)));
727 }
728 break;
729 }
730
731 case Token::BIT_OR:
732 case Token::BIT_XOR:
733 case Token::BIT_AND: {
734 if (reversed_) {
735 __ mov(r1, Operand(Smi::FromInt(value_)));
736 } else {
737 __ mov(r1, Operand(r0));
738 __ mov(r0, Operand(Smi::FromInt(value_)));
739 }
740 break;
741 }
742
743 case Token::SHL:
744 case Token::SHR:
745 case Token::SAR: {
746 if (!reversed_) {
747 __ mov(r1, Operand(r0));
748 __ mov(r0, Operand(Smi::FromInt(value_)));
749 } else {
750 UNREACHABLE(); // should have been handled in SmiOperation
751 }
752 break;
753 }
754
755 default:
756 // other cases should have been handled before this point.
757 UNREACHABLE();
758 break;
759 }
760
761 GenericBinaryOpStub igostub(op_);
762 __ CallStub(&igostub);
763 }
764 714
765 private: 715 private:
766 Token::Value op_; 716 Token::Value op_;
767 int value_; 717 int value_;
768 bool reversed_; 718 bool reversed_;
769 }; 719 };
770 720
771 721
722 void DeferredInlineSmiOperation::Generate() {
723 enter()->Bind();
724 VirtualFrame::SpilledScope spilled_scope(generator());
725
726 switch (op_) {
727 case Token::ADD: {
728 if (reversed_) {
729 // revert optimistic add
730 __ sub(r0, r0, Operand(Smi::FromInt(value_)));
731 __ mov(r1, Operand(Smi::FromInt(value_))); // x
Mads Ager (chromium) 2009/02/17 08:01:20 This comment seems old and out of context here. R
Kevin Millikin (Chromium) 2009/02/17 08:08:44 Done.
732 } else {
733 // revert optimistic add
734 __ sub(r1, r0, Operand(Smi::FromInt(value_)));
735 __ mov(r0, Operand(Smi::FromInt(value_)));
736 }
737 break;
738 }
739
740 case Token::SUB: {
741 if (reversed_) {
742 // revert optimistic sub
743 __ rsb(r0, r0, Operand(Smi::FromInt(value_)));
744 __ mov(r1, Operand(Smi::FromInt(value_)));
745 } else {
746 __ add(r1, r0, Operand(Smi::FromInt(value_)));
747 __ mov(r0, Operand(Smi::FromInt(value_)));
748 }
749 break;
750 }
751
752 case Token::BIT_OR:
753 case Token::BIT_XOR:
754 case Token::BIT_AND: {
755 if (reversed_) {
756 __ mov(r1, Operand(Smi::FromInt(value_)));
757 } else {
758 __ mov(r1, Operand(r0));
759 __ mov(r0, Operand(Smi::FromInt(value_)));
760 }
761 break;
762 }
763
764 case Token::SHL:
765 case Token::SHR:
766 case Token::SAR: {
767 if (!reversed_) {
768 __ mov(r1, Operand(r0));
769 __ mov(r0, Operand(Smi::FromInt(value_)));
770 } else {
771 UNREACHABLE(); // should have been handled in SmiOperation
772 }
773 break;
774 }
775
776 default:
777 // other cases should have been handled before this point.
778 UNREACHABLE();
779 break;
780 }
781
782 GenericBinaryOpStub igostub(op_);
783 Result arg0 = generator()->allocator()->Allocate(r0);
784 ASSERT(arg0.is_valid());
785 Result arg1 = generator()->allocator()->Allocate(r1);
786 ASSERT(arg1.is_valid());
787 generator()->frame()->CallStub(&igostub, &arg0, &arg1, 0);
788 exit()->Jump();
789 }
790
791
772 void CodeGenerator::SmiOperation(Token::Value op, 792 void CodeGenerator::SmiOperation(Token::Value op,
773 Handle<Object> value, 793 Handle<Object> value,
774 bool reversed) { 794 bool reversed) {
775 VirtualFrame::SpilledScope spilled_scope(this); 795 VirtualFrame::SpilledScope spilled_scope(this);
776 // NOTE: This is an attempt to inline (a bit) more of the code for 796 // NOTE: This is an attempt to inline (a bit) more of the code for
777 // some possible smi operations (like + and -) when (at least) one 797 // some possible smi operations (like + and -) when (at least) one
778 // of the operands is a literal smi. With this optimization, the 798 // of the operands is a literal smi. With this optimization, the
779 // performance of the system is increased by ~15%, and the generated 799 // performance of the system is increased by ~15%, and the generated
780 // code size is increased by ~1% (measured on a combination of 800 // code size is increased by ~1% (measured on a combination of
781 // different benchmarks). 801 // different benchmarks).
782 802
783 // sp[0] : operand 803 // sp[0] : operand
784 804
785 int int_value = Smi::cast(*value)->value(); 805 int int_value = Smi::cast(*value)->value();
786 806
787 JumpTarget exit(this); 807 JumpTarget exit(this);
788 frame_->EmitPop(r0); 808 frame_->EmitPop(r0);
789 809
790 switch (op) { 810 switch (op) {
791 case Token::ADD: { 811 case Token::ADD: {
792 DeferredCode* deferred = 812 DeferredCode* deferred =
793 new DeferredInlinedSmiOperation(this, op, int_value, reversed); 813 new DeferredInlineSmiOperation(this, op, int_value, reversed);
794 814
795 __ add(r0, r0, Operand(value), SetCC); 815 __ add(r0, r0, Operand(value), SetCC);
796 deferred->enter()->Branch(vs); 816 deferred->enter()->Branch(vs);
797 __ tst(r0, Operand(kSmiTagMask)); 817 __ tst(r0, Operand(kSmiTagMask));
798 deferred->enter()->Branch(ne); 818 deferred->enter()->Branch(ne);
799 deferred->exit()->Bind(); 819 deferred->exit()->Bind();
800 break; 820 break;
801 } 821 }
802 822
803 case Token::SUB: { 823 case Token::SUB: {
804 DeferredCode* deferred = 824 DeferredCode* deferred =
805 new DeferredInlinedSmiOperation(this, op, int_value, reversed); 825 new DeferredInlineSmiOperation(this, op, int_value, reversed);
806 826
807 if (!reversed) { 827 if (!reversed) {
808 __ sub(r0, r0, Operand(value), SetCC); 828 __ sub(r0, r0, Operand(value), SetCC);
809 } else { 829 } else {
810 __ rsb(r0, r0, Operand(value), SetCC); 830 __ rsb(r0, r0, Operand(value), SetCC);
811 } 831 }
812 deferred->enter()->Branch(vs); 832 deferred->enter()->Branch(vs);
813 __ tst(r0, Operand(kSmiTagMask)); 833 __ tst(r0, Operand(kSmiTagMask));
814 deferred->enter()->Branch(ne); 834 deferred->enter()->Branch(ne);
815 deferred->exit()->Bind(); 835 deferred->exit()->Bind();
816 break; 836 break;
817 } 837 }
818 838
819 case Token::BIT_OR: 839 case Token::BIT_OR:
820 case Token::BIT_XOR: 840 case Token::BIT_XOR:
821 case Token::BIT_AND: { 841 case Token::BIT_AND: {
822 DeferredCode* deferred = 842 DeferredCode* deferred =
823 new DeferredInlinedSmiOperation(this, op, int_value, reversed); 843 new DeferredInlineSmiOperation(this, op, int_value, reversed);
824 __ tst(r0, Operand(kSmiTagMask)); 844 __ tst(r0, Operand(kSmiTagMask));
825 deferred->enter()->Branch(ne); 845 deferred->enter()->Branch(ne);
826 switch (op) { 846 switch (op) {
827 case Token::BIT_OR: __ orr(r0, r0, Operand(value)); break; 847 case Token::BIT_OR: __ orr(r0, r0, Operand(value)); break;
828 case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break; 848 case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break;
829 case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break; 849 case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break;
830 default: UNREACHABLE(); 850 default: UNREACHABLE();
831 } 851 }
832 deferred->exit()->Bind(); 852 deferred->exit()->Bind();
833 break; 853 break;
834 } 854 }
835 855
836 case Token::SHL: 856 case Token::SHL:
837 case Token::SHR: 857 case Token::SHR:
838 case Token::SAR: { 858 case Token::SAR: {
839 if (reversed) { 859 if (reversed) {
840 __ mov(ip, Operand(value)); 860 __ mov(ip, Operand(value));
841 frame_->EmitPush(ip); 861 frame_->EmitPush(ip);
842 frame_->EmitPush(r0); 862 frame_->EmitPush(r0);
843 GenericBinaryOperation(op); 863 GenericBinaryOperation(op);
844 864
845 } else { 865 } else {
846 int shift_value = int_value & 0x1f; // least significant 5 bits 866 int shift_value = int_value & 0x1f; // least significant 5 bits
847 DeferredCode* deferred = 867 DeferredCode* deferred =
848 new DeferredInlinedSmiOperation(this, op, shift_value, false); 868 new DeferredInlineSmiOperation(this, op, shift_value, false);
849 __ tst(r0, Operand(kSmiTagMask)); 869 __ tst(r0, Operand(kSmiTagMask));
850 deferred->enter()->Branch(ne); 870 deferred->enter()->Branch(ne);
851 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags 871 __ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
852 switch (op) { 872 switch (op) {
853 case Token::SHL: { 873 case Token::SHL: {
854 __ mov(r2, Operand(r2, LSL, shift_value)); 874 __ mov(r2, Operand(r2, LSL, shift_value));
855 // check that the *unsigned* result fits in a smi 875 // check that the *unsigned* result fits in a smi
856 __ add(r3, r2, Operand(0x40000000), SetCC); 876 __ add(r3, r2, Operand(0x40000000), SetCC);
857 deferred->enter()->Branch(mi); 877 deferred->enter()->Branch(mi);
858 break; 878 break;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 ncr = LESS; 967 ncr = LESS;
948 } 968 }
949 frame_->EmitPush(r0); 969 frame_->EmitPush(r0);
950 arg_count++; 970 arg_count++;
951 __ mov(r0, Operand(Smi::FromInt(ncr))); 971 __ mov(r0, Operand(Smi::FromInt(ncr)));
952 } 972 }
953 973
954 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 974 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
955 // tagged as a small integer. 975 // tagged as a small integer.
956 frame_->EmitPush(r0); 976 frame_->EmitPush(r0);
957 __ mov(r0, Operand(arg_count)); 977 Result arg_count_register = allocator_->Allocate(r0);
958 frame_->InvokeBuiltin(native, CALL_JS, arg_count + 1); 978 ASSERT(arg_count_register.is_valid());
959 __ cmp(r0, Operand(0)); 979 __ mov(arg_count_register.reg(), Operand(arg_count));
980 Result result = frame_->InvokeBuiltin(native,
981 CALL_JS,
982 &arg_count_register,
983 arg_count + 1);
984 __ cmp(result.reg(), Operand(0));
985 result.Unuse();
960 exit.Jump(); 986 exit.Jump();
961 987
962 // test smi equality by pointer comparison. 988 // test smi equality by pointer comparison.
963 smi.Bind(); 989 smi.Bind();
964 __ cmp(r1, Operand(r0)); 990 __ cmp(r1, Operand(r0));
965 991
966 exit.Bind(); 992 exit.Bind();
967 cc_reg_ = cc; 993 cc_reg_ = cc;
968 } 994 }
969 995
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 } 1062 }
1037 1063
1038 1064
1039 void CodeGenerator::VisitBlock(Block* node) { 1065 void CodeGenerator::VisitBlock(Block* node) {
1040 VirtualFrame::SpilledScope spilled_scope(this); 1066 VirtualFrame::SpilledScope spilled_scope(this);
1041 Comment cmnt(masm_, "[ Block"); 1067 Comment cmnt(masm_, "[ Block");
1042 CodeForStatementPosition(node); 1068 CodeForStatementPosition(node);
1043 node->set_break_stack_height(break_stack_height_); 1069 node->set_break_stack_height(break_stack_height_);
1044 node->break_target()->Initialize(this); 1070 node->break_target()->Initialize(this);
1045 VisitStatementsAndSpill(node->statements()); 1071 VisitStatementsAndSpill(node->statements());
1046 node->break_target()->Bind(); 1072 if (node->break_target()->is_linked()) {
1073 node->break_target()->Bind();
1074 }
1047 } 1075 }
1048 1076
1049 1077
1050 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1078 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1051 VirtualFrame::SpilledScope spilled_scope(this); 1079 VirtualFrame::SpilledScope spilled_scope(this);
1052 __ mov(r0, Operand(pairs)); 1080 __ mov(r0, Operand(pairs));
1053 frame_->EmitPush(r0); 1081 frame_->EmitPush(r0);
1054 frame_->EmitPush(cp); 1082 frame_->EmitPush(cp);
1055 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); 1083 __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
1056 frame_->EmitPush(r0); 1084 frame_->EmitPush(r0);
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 } 1483 }
1456 } 1484 }
1457 1485
1458 1486
1459 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { 1487 void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
1460 VirtualFrame::SpilledScope spilled_scope(this); 1488 VirtualFrame::SpilledScope spilled_scope(this);
1461 Comment cmnt(masm_, "[ LoopStatement"); 1489 Comment cmnt(masm_, "[ LoopStatement");
1462 CodeForStatementPosition(node); 1490 CodeForStatementPosition(node);
1463 node->set_break_stack_height(break_stack_height_); 1491 node->set_break_stack_height(break_stack_height_);
1464 node->break_target()->Initialize(this); 1492 node->break_target()->Initialize(this);
1465 node->continue_target()->Initialize(this);
1466 1493
1467 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a 1494 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
1468 // known result for the test expression, with no side effects. 1495 // known result for the test expression, with no side effects.
1469 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; 1496 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW;
1470 if (node->cond() == NULL) { 1497 if (node->cond() == NULL) {
1471 ASSERT(node->type() == LoopStatement::FOR_LOOP); 1498 ASSERT(node->type() == LoopStatement::FOR_LOOP);
1472 info = ALWAYS_TRUE; 1499 info = ALWAYS_TRUE;
1473 } else { 1500 } else {
1474 Literal* lit = node->cond()->AsLiteral(); 1501 Literal* lit = node->cond()->AsLiteral();
1475 if (lit != NULL) { 1502 if (lit != NULL) {
1476 if (lit->IsTrue()) { 1503 if (lit->IsTrue()) {
1477 info = ALWAYS_TRUE; 1504 info = ALWAYS_TRUE;
1478 } else if (lit->IsFalse()) { 1505 } else if (lit->IsFalse()) {
1479 info = ALWAYS_FALSE; 1506 info = ALWAYS_FALSE;
1480 } 1507 }
1481 } 1508 }
1482 } 1509 }
1483 1510
1484 switch (node->type()) { 1511 switch (node->type()) {
1485 case LoopStatement::DO_LOOP: { 1512 case LoopStatement::DO_LOOP: {
1486 JumpTarget body(this); 1513 JumpTarget body(this, JumpTarget::BIDIRECTIONAL);
1487 // Label the body. 1514
1515 // Label the top of the loop for the backward CFG edge. If the test
1516 // is always true we can use the continue target, and if the test is
1517 // always false there is no need.
1488 if (info == ALWAYS_TRUE) { 1518 if (info == ALWAYS_TRUE) {
1519 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
1489 node->continue_target()->Bind(); 1520 node->continue_target()->Bind();
1490 } else if (info == ALWAYS_FALSE) { 1521 } else if (info == ALWAYS_FALSE) {
1491 // There is no need, we will never jump back. 1522 node->continue_target()->Initialize(this);
1492 } else { 1523 } else {
1493 ASSERT(info == DONT_KNOW); 1524 ASSERT(info == DONT_KNOW);
1525 node->continue_target()->Initialize(this);
1494 body.Bind(); 1526 body.Bind();
1495 } 1527 }
1528
1496 CheckStack(); // TODO(1222600): ignore if body contains calls. 1529 CheckStack(); // TODO(1222600): ignore if body contains calls.
1497 VisitAndSpill(node->body()); 1530 VisitAndSpill(node->body());
1498 1531
1499 // Compile the "test". 1532 // Compile the test.
1500 if (info == ALWAYS_TRUE) { 1533 if (info == ALWAYS_TRUE) {
1501 if (frame_ != NULL) { 1534 if (has_valid_frame()) {
1502 // If control can fall off the end of the body, jump back to the 1535 // If control can fall off the end of the body, jump back to the
1503 // top. 1536 // top.
1504 node->continue_target()->Jump(); 1537 node->continue_target()->Jump();
1505 } 1538 }
1506 } else if (info == ALWAYS_FALSE) { 1539 } else if (info == ALWAYS_FALSE) {
1507 // If we have a continue in the body, we only have to bind its jump 1540 // If we have a continue in the body, we only have to bind its jump
1508 // target. 1541 // target.
1509 if (node->continue_target()->is_linked()) { 1542 if (node->continue_target()->is_linked()) {
1510 node->continue_target()->Bind(); 1543 node->continue_target()->Bind();
1511 } 1544 }
1512 } else { 1545 } else {
1513 ASSERT(info == DONT_KNOW); 1546 ASSERT(info == DONT_KNOW);
1514 // We have to compile the test expression if it can be reached by 1547 // We have to compile the test expression if it can be reached by
1515 // control flow falling out of the body or via continue. 1548 // control flow falling out of the body or via continue.
1516 if (frame_ != NULL || node->continue_target()->is_linked()) { 1549 if (node->continue_target()->is_linked()) {
1517 node->continue_target()->Bind(); 1550 node->continue_target()->Bind();
1551 }
1552 if (has_valid_frame()) {
1518 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1553 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1519 &body, node->break_target(), true); 1554 &body, node->break_target(), true);
1520 if (frame_ != NULL) { 1555 if (has_valid_frame()) {
1521 // A NULL frame here indicates that control did not fall out of 1556 // A invalid frame here indicates that control did not
1522 // the test expression. 1557 // fall out of the test expression.
1523 Branch(true, &body); 1558 Branch(true, &body);
1524 } 1559 }
1525 } 1560 }
1526 } 1561 }
1527 break; 1562 break;
1528 } 1563 }
1529 1564
1530 case LoopStatement::WHILE_LOOP: { 1565 case LoopStatement::WHILE_LOOP: {
1531 JumpTarget body(this); 1566 // If the test is never true and has no side effects there is no need
1532 // Generate the loop header. 1567 // to compile the test or body.
1533 if (info == ALWAYS_TRUE) { 1568 if (info == ALWAYS_FALSE) break;
1534 // Merely label the body with the continue target. 1569
1535 node->continue_target()->Bind(); 1570 // Label the top of the loop with the continue target for the backward
1536 } else if (info == ALWAYS_FALSE) { 1571 // CFG edge.
1537 // There is no need to even compile the test or body. 1572 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
1538 break; 1573 node->continue_target()->Bind();
1539 } else { 1574
1540 // Compile the test labeled with the continue target and label the 1575 if (info == DONT_KNOW) {
1541 // body with the body target. 1576 JumpTarget body(this);
1542 ASSERT(info == DONT_KNOW);
1543 node->continue_target()->Bind();
1544 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1577 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1545 &body, node->break_target(), true); 1578 &body, node->break_target(), true);
1546 if (frame_ != NULL) { 1579 if (has_valid_frame()) {
1547 // A NULL frame indicates that control did not fall out of the 1580 // A NULL frame indicates that control did not fall out of the
1548 // test expression. 1581 // test expression.
1549 Branch(false, node->break_target()); 1582 Branch(false, node->break_target());
1550 } 1583 }
1551 if (frame_ != NULL || body.is_linked()) { 1584 if (has_valid_frame() || body.is_linked()) {
1552 body.Bind(); 1585 body.Bind();
1553 } 1586 }
1554 } 1587 }
1555 if (frame_ != NULL) { 1588
1589 if (has_valid_frame()) {
1556 CheckStack(); // TODO(1222600): ignore if body contains calls. 1590 CheckStack(); // TODO(1222600): ignore if body contains calls.
1557 VisitAndSpill(node->body()); 1591 VisitAndSpill(node->body());
1558 1592
1559 // If control flow can fall out of the body, jump back to the top. 1593 // If control flow can fall out of the body, jump back to the top.
1560 if (frame_ != NULL) { 1594 if (has_valid_frame()) {
1561 node->continue_target()->Jump(); 1595 node->continue_target()->Jump();
1562 } 1596 }
1563 } 1597 }
1564 break; 1598 break;
1565 } 1599 }
1566 1600
1567 case LoopStatement::FOR_LOOP: { 1601 case LoopStatement::FOR_LOOP: {
1568 JumpTarget loop(this); 1602 JumpTarget loop(this, JumpTarget::BIDIRECTIONAL);
1569 JumpTarget body(this); 1603
1570 if (node->init() != NULL) { 1604 if (node->init() != NULL) {
1571 VisitAndSpill(node->init()); 1605 VisitAndSpill(node->init());
1572 } 1606 }
1573 1607
1574 // There is no need to compile the test or body. 1608 // There is no need to compile the test or body.
1575 if (info == ALWAYS_FALSE) break; 1609 if (info == ALWAYS_FALSE) break;
1576 1610
1577 // If there is no update statement, label the top of the loop with the 1611 // If there is no update statement, label the top of the loop with the
1578 // continue target, otherwise with the loop target. 1612 // continue target, otherwise with the loop target.
1579 if (node->next() == NULL) { 1613 if (node->next() == NULL) {
1614 node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL);
1580 node->continue_target()->Bind(); 1615 node->continue_target()->Bind();
1581 } else { 1616 } else {
1617 node->continue_target()->Initialize(this);
1582 loop.Bind(); 1618 loop.Bind();
1583 } 1619 }
1584 1620
1585 // If the test is always true, there is no need to compile it. 1621 // If the test is always true, there is no need to compile it.
1586 if (info == DONT_KNOW) { 1622 if (info == DONT_KNOW) {
1623 JumpTarget body(this);
1587 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, 1624 LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
1588 &body, node->break_target(), true); 1625 &body, node->break_target(), true);
1589 if (frame_ != NULL) { 1626 if (has_valid_frame()) {
1590 Branch(false, node->break_target()); 1627 Branch(false, node->break_target());
1591 } 1628 }
1592 if (frame_ != NULL || body.is_linked()) { 1629 if (has_valid_frame() || body.is_linked()) {
1593 body.Bind(); 1630 body.Bind();
1594 } 1631 }
1595 } 1632 }
1596 1633
1597 if (frame_ != NULL) { 1634 if (has_valid_frame()) {
1598 CheckStack(); // TODO(1222600): ignore if body contains calls. 1635 CheckStack(); // TODO(1222600): ignore if body contains calls.
1599 VisitAndSpill(node->body()); 1636 VisitAndSpill(node->body());
1600 1637
1601 if (node->next() == NULL) { 1638 if (node->next() == NULL) {
1602 // If there is no update statement and control flow can fall out 1639 // If there is no update statement and control flow can fall out
1603 // of the loop, jump directly to the continue label. 1640 // of the loop, jump directly to the continue label.
1604 if (frame_ != NULL) { 1641 if (has_valid_frame()) {
1605 node->continue_target()->Jump(); 1642 node->continue_target()->Jump();
1606 } 1643 }
1607 } else { 1644 } else {
1608 // If there is an update statement and control flow can reach it 1645 // If there is an update statement and control flow can reach it
1609 // via falling out of the body of the loop or continuing, we 1646 // via falling out of the body of the loop or continuing, we
1610 // compile the update statement. 1647 // compile the update statement.
1611 if (frame_ != NULL || node->continue_target()->is_linked()) { 1648 if (node->continue_target()->is_linked()) {
1612 node->continue_target()->Bind(); 1649 node->continue_target()->Bind();
1650 }
1651 if (has_valid_frame()) {
1613 // Record source position of the statement as this code which is 1652 // Record source position of the statement as this code which is
1614 // after the code for the body actually belongs to the loop 1653 // after the code for the body actually belongs to the loop
1615 // statement and not the body. 1654 // statement and not the body.
1616 CodeForStatementPosition(node); 1655 CodeForStatementPosition(node);
1617
1618 VisitAndSpill(node->next()); 1656 VisitAndSpill(node->next());
1619 loop.Jump(); 1657 loop.Jump();
1620 } 1658 }
1621 } 1659 }
1622 } 1660 }
1623 break; 1661 break;
1624 } 1662 }
1625 } 1663 }
1626 1664
1627 if (node->break_target()->is_linked()) { 1665 if (node->break_target()->is_linked()) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1673 // Check if enumerable is already a JSObject 1711 // Check if enumerable is already a JSObject
1674 __ tst(r0, Operand(kSmiTagMask)); 1712 __ tst(r0, Operand(kSmiTagMask));
1675 primitive.Branch(eq); 1713 primitive.Branch(eq);
1676 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1714 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
1677 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 1715 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
1678 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 1716 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
1679 jsobject.Branch(hs); 1717 jsobject.Branch(hs);
1680 1718
1681 primitive.Bind(); 1719 primitive.Bind();
1682 frame_->EmitPush(r0); 1720 frame_->EmitPush(r0);
1683 __ mov(r0, Operand(0)); 1721 Result arg_count = allocator_->Allocate(r0);
1684 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, 1); 1722 ASSERT(arg_count.is_valid());
1723 __ mov(arg_count.reg(), Operand(0));
1724 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1);
1685 1725
1686 1726
1687 jsobject.Bind(); 1727 jsobject.Bind();
1688 1728
1689 // Get the set of properties (as a FixedArray or Map). 1729 // Get the set of properties (as a FixedArray or Map).
1690 frame_->EmitPush(r0); // duplicate the object being enumerated 1730 frame_->EmitPush(r0); // duplicate the object being enumerated
1691 frame_->EmitPush(r0); 1731 frame_->EmitPush(r0);
1692 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1732 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1693 1733
1694 // If we got a Map, we can do a fast modification check. 1734 // If we got a Map, we can do a fast modification check.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 // If not, we have to filter the key. 1794 // If not, we have to filter the key.
1755 __ ldr(r1, frame_->ElementAt(4)); 1795 __ ldr(r1, frame_->ElementAt(4));
1756 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 1796 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
1757 __ cmp(r1, Operand(r2)); 1797 __ cmp(r1, Operand(r2));
1758 end_del_check.Branch(eq); 1798 end_del_check.Branch(eq);
1759 1799
1760 // Convert the entry to a string (or null if it isn't a property anymore). 1800 // Convert the entry to a string (or null if it isn't a property anymore).
1761 __ ldr(r0, frame_->ElementAt(4)); // push enumerable 1801 __ ldr(r0, frame_->ElementAt(4)); // push enumerable
1762 frame_->EmitPush(r0); 1802 frame_->EmitPush(r0);
1763 frame_->EmitPush(r3); // push entry 1803 frame_->EmitPush(r3); // push entry
1764 __ mov(r0, Operand(1)); 1804 Result arg_count_register = allocator_->Allocate(r0);
1765 frame_->InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS, 2); 1805 ASSERT(arg_count_register.is_valid());
1766 __ mov(r3, Operand(r0)); 1806 __ mov(arg_count_register.reg(), Operand(1));
1807 Result result = frame_->InvokeBuiltin(Builtins::FILTER_KEY,
1808 CALL_JS,
1809 &arg_count_register,
1810 2);
1811 __ mov(r3, Operand(result.reg()));
1812 result.Unuse();
1767 1813
1768 // If the property has been removed while iterating, we just skip it. 1814 // If the property has been removed while iterating, we just skip it.
1769 __ cmp(r3, Operand(Factory::null_value())); 1815 __ cmp(r3, Operand(Factory::null_value()));
1770 node->continue_target()->Branch(eq); 1816 node->continue_target()->Branch(eq);
1771 1817
1772 end_del_check.Bind(); 1818 end_del_check.Bind();
1773 // Store the entry in the 'each' expression and take another spin in the 1819 // Store the entry in the 'each' expression and take another spin in the
1774 // loop. r3: i'th entry of the enum cache (or string there of) 1820 // loop. r3: i'th entry of the enum cache (or string there of)
1775 frame_->EmitPush(r3); // push entry 1821 frame_->EmitPush(r3); // push entry
1776 { Reference each(this, node->each()); 1822 { Reference each(this, node->each());
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
2264 // This deferred code stub will be used for creating the boilerplate 2310 // This deferred code stub will be used for creating the boilerplate
2265 // by calling Runtime_CreateObjectLiteral. 2311 // by calling Runtime_CreateObjectLiteral.
2266 // Each created boilerplate is stored in the JSFunction and they are 2312 // Each created boilerplate is stored in the JSFunction and they are
2267 // therefore context dependent. 2313 // therefore context dependent.
2268 class ObjectLiteralDeferred: public DeferredCode { 2314 class ObjectLiteralDeferred: public DeferredCode {
2269 public: 2315 public:
2270 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node) 2316 ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node)
2271 : DeferredCode(generator), node_(node) { 2317 : DeferredCode(generator), node_(node) {
2272 set_comment("[ ObjectLiteralDeferred"); 2318 set_comment("[ ObjectLiteralDeferred");
2273 } 2319 }
2320
2274 virtual void Generate(); 2321 virtual void Generate();
2322
2275 private: 2323 private:
2276 ObjectLiteral* node_; 2324 ObjectLiteral* node_;
2277 }; 2325 };
2278 2326
2279 2327
2280 void ObjectLiteralDeferred::Generate() { 2328 void ObjectLiteralDeferred::Generate() {
2329 // Argument is passed in r1.
2330 enter()->Bind();
2331 VirtualFrame::SpilledScope spilled_scope(generator());
2332
2281 // If the entry is undefined we call the runtime system to computed 2333 // If the entry is undefined we call the runtime system to computed
2282 // the literal. 2334 // the literal.
2283 2335
2336 VirtualFrame* frame = generator()->frame();
2284 // Literal array (0). 2337 // Literal array (0).
2285 __ push(r1); 2338 frame->Push(r1);
2286 // Literal index (1). 2339 // Literal index (1).
2287 __ mov(r0, Operand(Smi::FromInt(node_->literal_index()))); 2340 __ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
2288 __ push(r0); 2341 frame->Push(r0);
2289 // Constant properties (2). 2342 // Constant properties (2).
2290 __ mov(r0, Operand(node_->constant_properties())); 2343 __ mov(r0, Operand(node_->constant_properties()));
2291 __ push(r0); 2344 frame->Push(r0);
2292 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2345 Result boilerplate =
2293 __ mov(r2, Operand(r0)); 2346 frame->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2347 __ mov(r2, Operand(boilerplate.reg()));
2348 // Result is returned in r2.
2349 exit()->Jump();
2294 } 2350 }
2295 2351
2296 2352
2297 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2353 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2298 VirtualFrame::SpilledScope spilled_scope(this); 2354 VirtualFrame::SpilledScope spilled_scope(this);
2299 Comment cmnt(masm_, "[ ObjectLiteral"); 2355 Comment cmnt(masm_, "[ ObjectLiteral");
2300 2356
2301 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2357 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
2302 2358
2303 // Retrieve the literal array and check the allocated entry. 2359 // Retrieve the literal array and check the allocated entry.
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
2709 LoadGlobal(); 2765 LoadGlobal();
2710 2766
2711 // Push the arguments ("left-to-right") on the stack. 2767 // Push the arguments ("left-to-right") on the stack.
2712 ZoneList<Expression*>* args = node->arguments(); 2768 ZoneList<Expression*>* args = node->arguments();
2713 int arg_count = args->length(); 2769 int arg_count = args->length();
2714 for (int i = 0; i < arg_count; i++) { 2770 for (int i = 0; i < arg_count; i++) {
2715 LoadAndSpill(args->at(i)); 2771 LoadAndSpill(args->at(i));
2716 } 2772 }
2717 2773
2718 // r0: the number of arguments. 2774 // r0: the number of arguments.
2719 __ mov(r0, Operand(arg_count)); 2775 Result num_args = allocator_->Allocate(r0);
2776 ASSERT(num_args.is_valid());
2777 __ mov(num_args.reg(), Operand(arg_count));
2720 2778
2721 // Load the function into r1 as per calling convention. 2779 // Load the function into r1 as per calling convention.
2722 __ ldr(r1, frame_->ElementAt(arg_count + 1)); 2780 Result function = allocator_->Allocate(r1);
2781 ASSERT(function.is_valid());
2782 __ ldr(function.reg(), frame_->ElementAt(arg_count + 1));
2723 2783
2724 // Call the construct call builtin that handles allocation and 2784 // Call the construct call builtin that handles allocation and
2725 // constructor invocation. 2785 // constructor invocation.
2726 CodeForSourcePosition(node->position()); 2786 CodeForSourcePosition(node->position());
2727 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 2787 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
2728 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, arg_count + 1); 2788 Result result = frame_->CallCodeObject(ic,
2789 RelocInfo::CONSTRUCT_CALL,
2790 &num_args,
2791 &function,
2792 arg_count + 1);
2729 2793
2730 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 2794 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
2731 __ str(r0, frame_->Top()); 2795 __ str(r0, frame_->Top());
2732 } 2796 }
2733 2797
2734 2798
2735 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 2799 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
2736 VirtualFrame::SpilledScope spilled_scope(this); 2800 VirtualFrame::SpilledScope spilled_scope(this);
2737 ASSERT(args->length() == 1); 2801 ASSERT(args->length() == 1);
2738 JumpTarget leave(this); 2802 JumpTarget leave(this);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2955 true_target(), 3019 true_target(),
2956 true); 3020 true);
2957 cc_reg_ = NegateCondition(cc_reg_); 3021 cc_reg_ = NegateCondition(cc_reg_);
2958 3022
2959 } else if (op == Token::DELETE) { 3023 } else if (op == Token::DELETE) {
2960 Property* property = node->expression()->AsProperty(); 3024 Property* property = node->expression()->AsProperty();
2961 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 3025 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
2962 if (property != NULL) { 3026 if (property != NULL) {
2963 LoadAndSpill(property->obj()); 3027 LoadAndSpill(property->obj());
2964 LoadAndSpill(property->key()); 3028 LoadAndSpill(property->key());
2965 __ mov(r0, Operand(1)); // not counting receiver 3029 Result arg_count = allocator_->Allocate(r0);
2966 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 3030 ASSERT(arg_count.is_valid());
3031 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
3032 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
2967 3033
2968 } else if (variable != NULL) { 3034 } else if (variable != NULL) {
2969 Slot* slot = variable->slot(); 3035 Slot* slot = variable->slot();
2970 if (variable->is_global()) { 3036 if (variable->is_global()) {
2971 LoadGlobal(); 3037 LoadGlobal();
2972 __ mov(r0, Operand(variable->name())); 3038 __ mov(r0, Operand(variable->name()));
2973 frame_->EmitPush(r0); 3039 frame_->EmitPush(r0);
2974 __ mov(r0, Operand(1)); // not counting receiver 3040 Result arg_count = allocator_->Allocate(r0);
2975 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 3041 ASSERT(arg_count.is_valid());
3042 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
3043 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
2976 3044
2977 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 3045 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
2978 // lookup the context holding the named variable 3046 // lookup the context holding the named variable
2979 frame_->EmitPush(cp); 3047 frame_->EmitPush(cp);
2980 __ mov(r0, Operand(variable->name())); 3048 __ mov(r0, Operand(variable->name()));
2981 frame_->EmitPush(r0); 3049 frame_->EmitPush(r0);
2982 frame_->CallRuntime(Runtime::kLookupContext, 2); 3050 frame_->CallRuntime(Runtime::kLookupContext, 2);
2983 // r0: context 3051 // r0: context
2984 frame_->EmitPush(r0); 3052 frame_->EmitPush(r0);
2985 __ mov(r0, Operand(variable->name())); 3053 __ mov(r0, Operand(variable->name()));
2986 frame_->EmitPush(r0); 3054 frame_->EmitPush(r0);
2987 __ mov(r0, Operand(1)); // not counting receiver 3055 Result arg_count = allocator_->Allocate(r0);
2988 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, 2); 3056 ASSERT(arg_count.is_valid());
3057 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
3058 frame_->InvokeBuiltin(Builtins::DELETE, CALL_JS, &arg_count, 2);
2989 3059
2990 } else { 3060 } else {
2991 // Default: Result of deleting non-global, not dynamically 3061 // Default: Result of deleting non-global, not dynamically
2992 // introduced variables is false. 3062 // introduced variables is false.
2993 __ mov(r0, Operand(Factory::false_value())); 3063 __ mov(r0, Operand(Factory::false_value()));
2994 } 3064 }
2995 3065
2996 } else { 3066 } else {
2997 // Default: Result of deleting expressions is true. 3067 // Default: Result of deleting expressions is true.
2998 LoadAndSpill(node->expression()); // may have side-effects 3068 LoadAndSpill(node->expression()); // may have side-effects
(...skipping 26 matching lines...) Expand all
3025 } 3095 }
3026 3096
3027 case Token::BIT_NOT: { 3097 case Token::BIT_NOT: {
3028 // smi check 3098 // smi check
3029 JumpTarget smi_label(this); 3099 JumpTarget smi_label(this);
3030 JumpTarget continue_label(this); 3100 JumpTarget continue_label(this);
3031 __ tst(r0, Operand(kSmiTagMask)); 3101 __ tst(r0, Operand(kSmiTagMask));
3032 smi_label.Branch(eq); 3102 smi_label.Branch(eq);
3033 3103
3034 frame_->EmitPush(r0); 3104 frame_->EmitPush(r0);
3035 __ mov(r0, Operand(0)); // not counting receiver 3105 Result arg_count = allocator_->Allocate(r0);
3036 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, 1); 3106 ASSERT(arg_count.is_valid());
3107 __ mov(arg_count.reg(), Operand(0)); // not counting receiver
3108 frame_->InvokeBuiltin(Builtins::BIT_NOT, CALL_JS, &arg_count, 1);
3037 3109
3038 continue_label.Jump(); 3110 continue_label.Jump();
3039 smi_label.Bind(); 3111 smi_label.Bind();
3040 __ mvn(r0, Operand(r0)); 3112 __ mvn(r0, Operand(r0));
3041 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag 3113 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag
3042 continue_label.Bind(); 3114 continue_label.Bind();
3043 break; 3115 break;
3044 } 3116 }
3045 3117
3046 case Token::VOID: 3118 case Token::VOID:
3047 // since the stack top is cached in r0, popping and then 3119 // since the stack top is cached in r0, popping and then
3048 // pushing a value can be done by just writing to r0. 3120 // pushing a value can be done by just writing to r0.
3049 __ mov(r0, Operand(Factory::undefined_value())); 3121 __ mov(r0, Operand(Factory::undefined_value()));
3050 break; 3122 break;
3051 3123
3052 case Token::ADD: { 3124 case Token::ADD: {
3053 // Smi check. 3125 // Smi check.
3054 JumpTarget continue_label(this); 3126 JumpTarget continue_label(this);
3055 __ tst(r0, Operand(kSmiTagMask)); 3127 __ tst(r0, Operand(kSmiTagMask));
3056 continue_label.Branch(eq); 3128 continue_label.Branch(eq);
3057 frame_->EmitPush(r0); 3129 frame_->EmitPush(r0);
3058 __ mov(r0, Operand(0)); // not counting receiver 3130 Result arg_count = allocator_->Allocate(r0);
3059 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); 3131 ASSERT(arg_count.is_valid());
3132 __ mov(arg_count.reg(), Operand(0)); // not counting receiver
3133 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, &arg_count, 1);
3060 continue_label.Bind(); 3134 continue_label.Bind();
3061 break; 3135 break;
3062 } 3136 }
3063 default: 3137 default:
3064 UNREACHABLE(); 3138 UNREACHABLE();
3065 } 3139 }
3066 frame_->EmitPush(r0); // r0 has result 3140 frame_->EmitPush(r0); // r0 has result
3067 } 3141 }
3068 } 3142 }
3069 3143
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
3453 break; 3527 break;
3454 3528
3455 case Token::GTE: 3529 case Token::GTE:
3456 Comparison(ge); 3530 Comparison(ge);
3457 break; 3531 break;
3458 3532
3459 case Token::EQ_STRICT: 3533 case Token::EQ_STRICT:
3460 Comparison(eq, true); 3534 Comparison(eq, true);
3461 break; 3535 break;
3462 3536
3463 case Token::IN: 3537 case Token::IN: {
3464 __ mov(r0, Operand(1)); // not counting receiver 3538 Result arg_count = allocator_->Allocate(r0);
3465 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); 3539 ASSERT(arg_count.is_valid());
3466 frame_->EmitPush(r0); 3540 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
3541 Result result = frame_->InvokeBuiltin(Builtins::IN,
3542 CALL_JS,
3543 &arg_count,
3544 2);
3545 frame_->EmitPush(result.reg());
3467 break; 3546 break;
3547 }
3468 3548
3469 case Token::INSTANCEOF: 3549 case Token::INSTANCEOF: {
3470 __ mov(r0, Operand(1)); // not counting receiver 3550 Result arg_count = allocator_->Allocate(r0);
3471 frame_->InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS, 2); 3551 ASSERT(arg_count.is_valid());
3472 __ tst(r0, Operand(r0)); 3552 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
3553 Result result = frame_->InvokeBuiltin(Builtins::INSTANCE_OF,
3554 CALL_JS,
3555 &arg_count,
3556 2);
3557 __ tst(result.reg(), Operand(result.reg()));
3473 cc_reg_ = eq; 3558 cc_reg_ = eq;
3474 break; 3559 break;
3560 }
3475 3561
3476 default: 3562 default:
3477 UNREACHABLE(); 3563 UNREACHABLE();
3478 } 3564 }
3479 } 3565 }
3480 3566
3481 3567
3482 #ifdef DEBUG 3568 #ifdef DEBUG
3483 bool CodeGenerator::HasValidEntryRegisters() { return true; } 3569 bool CodeGenerator::HasValidEntryRegisters() { return true; }
3484 #endif 3570 #endif
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 exit.Bind(); 3755 exit.Bind();
3670 } 3756 }
3671 } 3757 }
3672 break; 3758 break;
3673 } 3759 }
3674 3760
3675 case NAMED: { 3761 case NAMED: {
3676 Comment cmnt(masm, "[ Store to named Property"); 3762 Comment cmnt(masm, "[ Store to named Property");
3677 // Call the appropriate IC code. 3763 // Call the appropriate IC code.
3678 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3764 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3679 frame->EmitPop(r0); // value 3765 Handle<String> name(GetName());
3766
3767 Result value = cgen_->allocator()->Allocate(r0);
3768 ASSERT(value.is_valid());
3769 frame->EmitPop(value.reg());
3770
3680 // Setup the name register. 3771 // Setup the name register.
3681 Handle<String> name(GetName()); 3772 Result property_name = cgen_->allocator()->Allocate(r2);
3682 __ mov(r2, Operand(name)); 3773 ASSERT(property_name.is_valid());
3683 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3774 __ mov(property_name.reg(), Operand(name));
3684 frame->EmitPush(r0); 3775 Result answer = frame->CallCodeObject(ic,
3776 RelocInfo::CODE_TARGET,
3777 &value,
3778 &property_name,
3779 0);
3780 frame->EmitPush(answer.reg());
3685 break; 3781 break;
3686 } 3782 }
3687 3783
3688 case KEYED: { 3784 case KEYED: {
3689 Comment cmnt(masm, "[ Store to keyed Property"); 3785 Comment cmnt(masm, "[ Store to keyed Property");
3690 Property* property = expression_->AsProperty(); 3786 Property* property = expression_->AsProperty();
3691 ASSERT(property != NULL); 3787 ASSERT(property != NULL);
3692 cgen_->CodeForSourcePosition(property->position()); 3788 cgen_->CodeForSourcePosition(property->position());
3693 3789
3694 // Call IC code. 3790 // Call IC code.
3695 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3791 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3696 // TODO(1222589): Make the IC grab the values from the stack. 3792 // TODO(1222589): Make the IC grab the values from the stack.
3697 frame->EmitPop(r0); // value 3793 Result value = cgen_->allocator()->Allocate(r0);
3698 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 3794 ASSERT(value.is_valid());
3699 frame->EmitPush(r0); 3795 frame->EmitPop(value.reg()); // value
3796 Result result =
3797 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, 0);
3798 frame->EmitPush(result.reg());
3700 break; 3799 break;
3701 } 3800 }
3702 3801
3703 default: 3802 default:
3704 UNREACHABLE(); 3803 UNREACHABLE();
3705 } 3804 }
3706 } 3805 }
3707 3806
3708 3807
3709 void GetPropertyStub::Generate(MacroAssembler* masm) { 3808 void GetPropertyStub::Generate(MacroAssembler* masm) {
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after
4608 __ mov(r2, Operand(0)); 4707 __ mov(r2, Operand(0));
4609 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 4708 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
4610 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 4709 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
4611 RelocInfo::CODE_TARGET); 4710 RelocInfo::CODE_TARGET);
4612 } 4711 }
4613 4712
4614 4713
4615 #undef __ 4714 #undef __
4616 4715
4617 } } // namespace v8::internal 4716 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698