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 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 // code by jumping to the return site. | 680 // code by jumping to the return site. |
681 function_return_.Jump(&return_value); | 681 function_return_.Jump(&return_value); |
682 } else { | 682 } else { |
683 function_return_.Bind(&return_value); | 683 function_return_.Bind(&return_value); |
684 GenerateReturnSequence(&return_value); | 684 GenerateReturnSequence(&return_value); |
685 } | 685 } |
686 } | 686 } |
687 } | 687 } |
688 | 688 |
689 | 689 |
690 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* a) { | 690 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
691 UNIMPLEMENTED(); | 691 ASSERT(!in_spilled_code()); |
692 } | 692 Comment cmnt(masm_, "[ WithEnterStatement"); |
693 CodeForStatementPosition(node); | |
694 Load(node->expression()); | |
695 Result context; | |
696 if (node->is_catch_block()) { | |
697 context = frame_->CallRuntime(Runtime::kPushCatchContext, 1); | |
698 } else { | |
699 context = frame_->CallRuntime(Runtime::kPushContext, 1); | |
700 } | |
693 | 701 |
694 void CodeGenerator::VisitWithExitStatement(WithExitStatement* a) { | 702 // Update context local. |
695 UNIMPLEMENTED(); | 703 frame_->SaveContextRegister(); |
696 } | |
697 | 704 |
698 void CodeGenerator::VisitSwitchStatement(SwitchStatement* a) { | 705 // Verify that the runtime call result and esi agree. |
William Hesse
2009/06/26 08:25:18
rsi
| |
699 UNIMPLEMENTED(); | 706 if (FLAG_debug_code) { |
707 __ cmpq(context.reg(), rsi); | |
708 __ Assert(equal, "Runtime::NewContext should end up in rsi"); | |
709 } | |
700 } | 710 } |
701 | 711 |
702 | 712 |
713 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | |
714 ASSERT(!in_spilled_code()); | |
715 Comment cmnt(masm_, "[ WithExitStatement"); | |
716 CodeForStatementPosition(node); | |
717 // Pop context. | |
718 __ movq(rsi, ContextOperand(rsi, Context::PREVIOUS_INDEX)); | |
719 // Update context local. | |
720 frame_->SaveContextRegister(); | |
721 } | |
722 | |
723 | |
724 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | |
725 // TODO(X64): This code is completely generic and should be moved somewhere | |
726 // where it can be shared between architectures. | |
727 ASSERT(!in_spilled_code()); | |
728 Comment cmnt(masm_, "[ SwitchStatement"); | |
729 CodeForStatementPosition(node); | |
730 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | |
731 | |
732 // Compile the switch value. | |
733 Load(node->tag()); | |
734 | |
735 ZoneList<CaseClause*>* cases = node->cases(); | |
736 int length = cases->length(); | |
737 CaseClause* default_clause = NULL; | |
738 | |
739 JumpTarget next_test; | |
740 // Compile the case label expressions and comparisons. Exit early | |
741 // if a comparison is unconditionally true. The target next_test is | |
742 // bound before the loop in order to indicate control flow to the | |
743 // first comparison. | |
744 next_test.Bind(); | |
745 for (int i = 0; i < length && !next_test.is_unused(); i++) { | |
746 CaseClause* clause = cases->at(i); | |
747 // The default is not a test, but remember it for later. | |
748 if (clause->is_default()) { | |
749 default_clause = clause; | |
750 continue; | |
751 } | |
752 | |
753 Comment cmnt(masm_, "[ Case comparison"); | |
754 // We recycle the same target next_test for each test. Bind it if | |
755 // the previous test has not done so and then unuse it for the | |
756 // loop. | |
757 if (next_test.is_linked()) { | |
758 next_test.Bind(); | |
759 } | |
760 next_test.Unuse(); | |
761 | |
762 // Duplicate the switch value. | |
763 frame_->Dup(); | |
764 | |
765 // Compile the label expression. | |
766 Load(clause->label()); | |
767 | |
768 // Compare and branch to the body if true or the next test if | |
769 // false. Prefer the next test as a fall through. | |
770 ControlDestination dest(clause->body_target(), &next_test, false); | |
771 Comparison(equal, true, &dest); | |
772 | |
773 // If the comparison fell through to the true target, jump to the | |
774 // actual body. | |
775 if (dest.true_was_fall_through()) { | |
776 clause->body_target()->Unuse(); | |
777 clause->body_target()->Jump(); | |
778 } | |
779 } | |
780 | |
781 // If there was control flow to a next test from the last one | |
782 // compiled, compile a jump to the default or break target. | |
783 if (!next_test.is_unused()) { | |
784 if (next_test.is_linked()) { | |
785 next_test.Bind(); | |
786 } | |
787 // Drop the switch value. | |
788 frame_->Drop(); | |
789 if (default_clause != NULL) { | |
790 default_clause->body_target()->Jump(); | |
791 } else { | |
792 node->break_target()->Jump(); | |
793 } | |
794 } | |
795 | |
796 // The last instruction emitted was a jump, either to the default | |
797 // clause or the break target, or else to a case body from the loop | |
798 // that compiles the tests. | |
799 ASSERT(!has_valid_frame()); | |
800 // Compile case bodies as needed. | |
801 for (int i = 0; i < length; i++) { | |
802 CaseClause* clause = cases->at(i); | |
803 | |
804 // There are two ways to reach the body: from the corresponding | |
805 // test or as the fall through of the previous body. | |
806 if (clause->body_target()->is_linked() || has_valid_frame()) { | |
807 if (clause->body_target()->is_linked()) { | |
808 if (has_valid_frame()) { | |
809 // If we have both a jump to the test and a fall through, put | |
810 // a jump on the fall through path to avoid the dropping of | |
811 // the switch value on the test path. The exception is the | |
812 // default which has already had the switch value dropped. | |
813 if (clause->is_default()) { | |
814 clause->body_target()->Bind(); | |
815 } else { | |
816 JumpTarget body; | |
817 body.Jump(); | |
818 clause->body_target()->Bind(); | |
819 frame_->Drop(); | |
820 body.Bind(); | |
821 } | |
822 } else { | |
823 // No fall through to worry about. | |
824 clause->body_target()->Bind(); | |
825 if (!clause->is_default()) { | |
826 frame_->Drop(); | |
827 } | |
828 } | |
829 } else { | |
830 // Otherwise, we have only fall through. | |
831 ASSERT(has_valid_frame()); | |
832 } | |
833 | |
834 // We are now prepared to compile the body. | |
835 Comment cmnt(masm_, "[ Case body"); | |
836 VisitStatements(clause->statements()); | |
837 } | |
838 clause->body_target()->Unuse(); | |
839 } | |
840 | |
841 // We may not have a valid frame here so bind the break target only | |
842 // if needed. | |
843 if (node->break_target()->is_linked()) { | |
844 node->break_target()->Bind(); | |
845 } | |
846 node->break_target()->Unuse(); | |
847 } | |
848 | |
849 | |
703 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { | 850 void CodeGenerator::VisitLoopStatement(LoopStatement* node) { |
704 ASSERT(!in_spilled_code()); | 851 ASSERT(!in_spilled_code()); |
705 Comment cmnt(masm_, "[ LoopStatement"); | 852 Comment cmnt(masm_, "[ LoopStatement"); |
706 CodeForStatementPosition(node); | 853 CodeForStatementPosition(node); |
707 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 854 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
708 | 855 |
709 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a | 856 // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a |
710 // known result for the test expression, with no side effects. | 857 // known result for the test expression, with no side effects. |
711 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; | 858 enum { ALWAYS_TRUE, ALWAYS_FALSE, DONT_KNOW } info = DONT_KNOW; |
712 if (node->cond() == NULL) { | 859 if (node->cond() == NULL) { |
(...skipping 5297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6010 break; | 6157 break; |
6011 default: | 6158 default: |
6012 UNREACHABLE(); | 6159 UNREACHABLE(); |
6013 } | 6160 } |
6014 } | 6161 } |
6015 | 6162 |
6016 | 6163 |
6017 #undef __ | 6164 #undef __ |
6018 | 6165 |
6019 } } // namespace v8::internal | 6166 } } // namespace v8::internal |
OLD | NEW |