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

Side by Side Diff: src/hydrogen.cc

Issue 10543138: Reimplemented HGraph::Postorder and HGraph::PostorderLoopBlocks iteratively to avoid stack overflow… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 6 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 | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 for (int i = 0; i < blocks()->length(); ++i) { 741 for (int i = 0; i < blocks()->length(); ++i) {
742 HInstruction* instr = blocks()->at(i)->first(); 742 HInstruction* instr = blocks()->at(i)->first();
743 while (instr != NULL) { 743 while (instr != NULL) {
744 HValue* value = instr->Canonicalize(); 744 HValue* value = instr->Canonicalize();
745 if (value != instr) instr->DeleteAndReplaceWith(value); 745 if (value != instr) instr->DeleteAndReplaceWith(value);
746 instr = instr->next(); 746 instr = instr->next();
747 } 747 }
748 } 748 }
749 } 749 }
750 750
751 // Block ordering was implemented with two mutually recursive methods,
752 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
753 // The recursion could lead to stack overflow so the algorithm has been
754 // implemented iteratively.
755 // At a _very_ high level the algorithm looks like this:
Jakob Kummerow 2012/06/14 17:24:14 Remove the "_very_". Just "high level". It's clean
756 //
757 // Postorder(block, loop_header) : {
758 // if (block has already been visited or is of another loop) return;
759 // mark block as visited;
760 // if (block is a loop header) {
761 // LoopMembersCycle(block, loop_header);
762 // SuccessorsOfLoopHeaderCycle(block, loop_header);
Jakob Kummerow 2012/06/14 17:24:14 This only needs "block" as input, right? That's th
763 // } else {
764 // PostorderCycle(block)
765 // }
766 // put block in result list;
767 // }
768 //
769 // LoopMembersCycle(block) {
Jakob Kummerow 2012/06/14 17:24:14 This needs a second argument "outer_loop_header".
770 // foreach (block b in block loop members) {
771 // SuccessorsOfLoopMemberCycle(b);
Jakob Kummerow 2012/06/14 17:24:14 This call must pass on the outer_loop_header.
772 // if (b is loop header) LoopMembersCycle(b);
773 // }
774 // }
775 //
776 // SuccessorsOfLoopMemberCycle(block, loop_header) {
Jakob Kummerow 2012/06/14 17:24:14 I'd rename the second argument to outer_loop_heade
777 // foreach (block b in block successors) Postorder(b, loop_header)
778 // }
779 //
780 // SuccessorsOfLoopHeaderCycle(block) {
781 // foreach (block b in block successors) Postorder(b, b)
Jakob Kummerow 2012/06/14 17:24:14 Shouldn't this pass (b, block) instead?
782 // }
783 //
784 // PostorderCycle(block, loop_header) {
Jakob Kummerow 2012/06/14 17:24:14 I don't feel strongly about this, but wouldn't s/P
785 // foreach (block b in block successors) Postorder(b, loop_header)
786 // }
787 //
788 // The ordering is started calling Postorder(entry, NULL).
789 //
790 // Each instance of PostorderProcessor represents the "stack frame" of the
791 // recursion, and particularly keeps the state of one of the cycles.
792 // To recycle memory we keep all the frames in a double linked list but
793 // this means that we cannot use constructors to initialize the frames.
794 //
795 class PostorderProcessor : ZoneObject {
Jakob Kummerow 2012/06/14 17:24:14 "...: public ZoneObject" please
796 public:
797 // Back list link (towards the stack bottom)
Jakob Kummerow 2012/06/14 17:24:14 nit: "Backward", and a missing full stop at the en
798 PostorderProcessor* father() {return father_; }
Jakob Kummerow 2012/06/14 17:24:14 nit: s/father/parent/? ;-)
799 // Forward list link (towards the stack top)
Jakob Kummerow 2012/06/14 17:24:14 nit: missing full stop at the end.
800 PostorderProcessor* child() {return child_; }
801 HBasicBlock* block() { return block_; }
802 HLoopInformation* loop() { return loop_; }
803 HBasicBlock* loop_header() { return loop_header_; }
804
805 static PostorderProcessor* CreateEntryProcessor(Zone* zone,
806 HBasicBlock* block,
807 BitVector* visited) {
808 PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
809 return result->SetupSuccessors(zone, block, NULL, visited);
810 }
811
812 PostorderProcessor* PerformStep(Zone* zone,
813 BitVector* visited,
814 ZoneList<HBasicBlock*>* order) {
815 PostorderProcessor* next =
816 PerformNonBacktrackingStep(zone, visited, order);
817 if (next != NULL) {
818 return next;
819 } else {
820 return Backtrack(zone, visited, order);
821 }
822 }
823
824 private:
825 // Each enum value states the cycle whose state is kept by this instance.
826 enum LoopKind {
827 NONE,
828 SUCCESSORS,
829 SUCCESSORS_OF_LOOP_HEADER,
830 LOOP_MEMBERS,
831 SUCCESSORS_OF_LOOP_MEMBER
832 };
833
834 // Each "Setup..." method is like a constructor for a cycle state.
835 PostorderProcessor* SetupSuccessors(Zone* zone,
836 HBasicBlock* block,
837 HBasicBlock* loop_header,
838 BitVector* visited) {
839 if ((block == NULL || visited->Contains(block->block_id())) ||
Jakob Kummerow 2012/06/14 17:24:14 nit: you can remove one pair of ().
840 (block->parent_loop_header() != loop_header)) {
Jakob Kummerow 2012/06/14 17:24:14 can remove the outer (...) here too
841 kind_ = NONE;
842 block_ = NULL;
843 loop_ = NULL;
844 loop_header_ = NULL;
845 return this;
846 } else {
847 block_ = block;
848 loop_ = NULL;
849 visited->Add(block->block_id());
850
851 if (block->IsLoopHeader()) {
852 kind_ = SUCCESSORS_OF_LOOP_HEADER;
853 loop_header_ = block;
854 InitializeSuccessors();
855 PostorderProcessor* result = Push(zone);
856 return result->SetupLoopMembers(zone, block, block->loop_information(),
857 loop_header);
858 } else {
859 ASSERT(block->IsFinished());
860 kind_ = SUCCESSORS;
861 loop_header_ = loop_header;
862 InitializeSuccessors();
863 return this;
864 }
865 }
866 }
867
868 PostorderProcessor* SetupLoopMembers(Zone* zone,
869 HBasicBlock* block,
870 HLoopInformation* loop,
871 HBasicBlock* loop_header) {
872 kind_ = LOOP_MEMBERS;
873 block_ = block;
874 loop_ = loop;
875 loop_header_ = loop_header;
876 InitializeLoopMembers();
877 return this;
878 }
879
880 PostorderProcessor* SetupSuccessorsOfLoopMember(
881 HBasicBlock* block,
882 HLoopInformation* loop,
883 HBasicBlock* loop_header) {
884 kind_ = SUCCESSORS_OF_LOOP_MEMBER;
885 block_ = block;
886 loop_ = loop;
887 loop_header_ = loop_header;
888 InitializeSuccessors();
889 return this;
890 }
891
892 // This method "allocates" a new stack frame.
893 PostorderProcessor* Push(Zone* zone) {
894 if (child_ == NULL) {
895 child_ = new(zone) PostorderProcessor(this);
896 }
897 return child_;
898 }
899
900 void ClosePostorder(ZoneList<HBasicBlock*>* order) {
901 ASSERT(block_->end()->FirstSuccessor() == NULL ||
902 order->Contains(block_->end()->FirstSuccessor()) ||
903 block_->end()->FirstSuccessor()->IsLoopHeader());
904 ASSERT(block_->end()->SecondSuccessor() == NULL ||
905 order->Contains(block_->end()->SecondSuccessor()) ||
906 block_->end()->SecondSuccessor()->IsLoopHeader());
907 order->Add(block_);
908 }
909
910 // This method is the basic block to walk up the stack.
911 PostorderProcessor* Pop(Zone* zone,
912 BitVector* visited,
913 ZoneList<HBasicBlock*>* order) {
914 switch (kind_) {
915 case SUCCESSORS:
916 case SUCCESSORS_OF_LOOP_HEADER:
917 ClosePostorder(order);
918 return father_;
919 case LOOP_MEMBERS:
920 return father_;
921 case SUCCESSORS_OF_LOOP_MEMBER:
922 if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
923 // In this case we need to perform a LOOP_MEMBERS cycle so we
924 // initialize it and return this instead of father.
925 return SetupLoopMembers(zone, block(),
926 block()->loop_information(), loop_header_);
927 } else {
928 return father_;
929 }
930 case NONE:
931 return father_;
932 default:
933 ASSERT(false);
Jakob Kummerow 2012/06/14 17:24:14 nit: we have UNREACHABLE() for this. Even better:
934 return NULL;
935 }
936 }
937
938 // Walks up the stack.
939 PostorderProcessor* Backtrack(Zone* zone,
940 BitVector* visited,
941 ZoneList<HBasicBlock*>* order) {
942 PostorderProcessor* father = Pop(zone, visited, order);
Jakob Kummerow 2012/06/14 17:24:14 Again, s/father/parent/.
943 while (father != NULL) {
944 PostorderProcessor* next =
945 father->PerformNonBacktrackingStep(zone, visited, order);
946 if (next != NULL) {
947 return next;
948 } else {
949 father = father->Pop(zone, visited, order);
950 }
951 }
952 return NULL;
953 }
954
955 PostorderProcessor* PerformNonBacktrackingStep(
956 Zone* zone,
957 BitVector* visited,
958 ZoneList<HBasicBlock*>* order) {
959 HBasicBlock* next_block;
960 switch (kind_) {
961 case SUCCESSORS:
962 next_block = AdvanceSuccessors();
963 if (next_block != NULL) {
964 PostorderProcessor* result = Push(zone);
965 return result->SetupSuccessors(zone, next_block,
966 loop_header_, visited);
967 }
968 break;
969 case SUCCESSORS_OF_LOOP_HEADER:
970 next_block = AdvanceSuccessors();
971 if (next_block != NULL) {
972 PostorderProcessor* result = Push(zone);
973 return result->SetupSuccessors(zone, next_block,
974 block(), visited);
975 }
976 break;
977 case LOOP_MEMBERS:
978 next_block = AdvanceLoopMembers();
979 if (next_block != NULL) {
980 PostorderProcessor* result = Push(zone);
981 return result->SetupSuccessorsOfLoopMember(next_block,
982 loop_, loop_header_);
983 }
984 break;
985 case SUCCESSORS_OF_LOOP_MEMBER:
986 next_block = AdvanceSuccessors();
987 if (next_block != NULL) {
988 PostorderProcessor* result = Push(zone);
989 return result->SetupSuccessors(zone, next_block,
990 loop_header_, visited);
991 }
992 break;
993 default:
Jakob Kummerow 2012/06/14 17:24:14 Again, please remove the default case.
Massi 2012/06/18 11:21:30 If I remove it I cannot compile, likewise if I rem
994 return NULL;
995 }
996 return NULL;
997 }
998
999 // The following two methods implement a "foreach b in successors" cycle.
1000 void InitializeSuccessors() {
1001 loop_index = 0;
1002 loop_length = 0;
1003 successor_iterator = HSuccessorIterator(block_->end());
1004 }
1005
1006 HBasicBlock* AdvanceSuccessors() {
1007 if (!successor_iterator.Done()) {
1008 HBasicBlock* result = successor_iterator.Current();
1009 successor_iterator.Advance();
1010 return result;
1011 } else {
Jakob Kummerow 2012/06/14 17:24:14 nit: You could remove the "else" and just "return
1012 return NULL;
1013 }
1014 }
1015
1016 // The following two methods implement a "foreach b in loop members" cycle.
1017 void InitializeLoopMembers() {
1018 loop_index = 0;
1019 loop_length = loop_->blocks()->length();
1020 }
1021
1022 HBasicBlock* AdvanceLoopMembers() {
1023 if (loop_index < loop_length) {
1024 HBasicBlock* result = loop_->blocks()->at(loop_index);
1025 loop_index++;
1026 return result;
1027 } else {
1028 return NULL;
1029 }
1030 }
1031
1032 explicit PostorderProcessor(PostorderProcessor* father)
Jakob Kummerow 2012/06/14 17:24:14 Please put the constructor first (within the "priv
1033 : father_(father), child_(NULL), successor_iterator(NULL) { }
1034
1035 LoopKind kind_;
1036 PostorderProcessor* father_;
1037 PostorderProcessor* child_;
1038 HLoopInformation* loop_;
1039 HBasicBlock* block_;
1040 HBasicBlock* loop_header_;
1041 int loop_index;
Jakob Kummerow 2012/06/14 17:24:14 nit: trailing _ please (again below, twice).
1042 int loop_length;
1043 HSuccessorIterator successor_iterator;
1044 };
1045
751 1046
752 void HGraph::OrderBlocks() { 1047 void HGraph::OrderBlocks() {
753 HPhase phase("H_Block ordering"); 1048 HPhase phase("H_Block ordering");
754 BitVector visited(blocks_.length(), zone()); 1049 BitVector visited(blocks_.length(), zone());
755 1050
756 ZoneList<HBasicBlock*> reverse_result(8); 1051 ZoneList<HBasicBlock*> reverse_result(8);
757 HBasicBlock* start = blocks_[0]; 1052 HBasicBlock* start = blocks_[0];
758 Postorder(start, &visited, &reverse_result, NULL); 1053 PostorderProcessor* postorder =
759 1054 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited);
1055 while (postorder != NULL) {
1056 postorder = postorder->PerformStep(zone(), &visited, &reverse_result);
1057 }
760 blocks_.Rewind(0); 1058 blocks_.Rewind(0);
761 int index = 0; 1059 int index = 0;
762 for (int i = reverse_result.length() - 1; i >= 0; --i) { 1060 for (int i = reverse_result.length() - 1; i >= 0; --i) {
763 HBasicBlock* b = reverse_result[i]; 1061 HBasicBlock* b = reverse_result[i];
764 blocks_.Add(b); 1062 blocks_.Add(b);
765 b->set_block_id(index++); 1063 b->set_block_id(index++);
766 } 1064 }
767 } 1065 }
768 1066
769 1067
770 void HGraph::PostorderLoopBlocks(HLoopInformation* loop, 1068 void HGraph::PostorderLoopBlocks(HLoopInformation* loop,
Jakob Kummerow 2012/06/14 17:24:14 I think you can remove this method and the next. T
771 BitVector* visited, 1069 BitVector* visited,
772 ZoneList<HBasicBlock*>* order, 1070 ZoneList<HBasicBlock*>* order,
773 HBasicBlock* loop_header) { 1071 HBasicBlock* loop_header) {
774 for (int i = 0; i < loop->blocks()->length(); ++i) { 1072 for (int i = 0; i < loop->blocks()->length(); ++i) {
775 HBasicBlock* b = loop->blocks()->at(i); 1073 HBasicBlock* b = loop->blocks()->at(i);
776 for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) { 1074 for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) {
777 Postorder(it.Current(), visited, order, loop_header); 1075 Postorder(it.Current(), visited, order, loop_header);
778 } 1076 }
779 if (b->IsLoopHeader() && b != loop->loop_header()) { 1077 if (b->IsLoopHeader() && b != loop->loop_header()) {
780 PostorderLoopBlocks(b->loop_information(), visited, order, loop_header); 1078 PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
(...skipping 8213 matching lines...) Expand 10 before | Expand all | Expand 10 after
8994 } 9292 }
8995 } 9293 }
8996 9294
8997 #ifdef DEBUG 9295 #ifdef DEBUG
8998 if (graph_ != NULL) graph_->Verify(false); // No full verify. 9296 if (graph_ != NULL) graph_->Verify(false); // No full verify.
8999 if (allocator_ != NULL) allocator_->Verify(); 9297 if (allocator_ != NULL) allocator_->Verify();
9000 #endif 9298 #endif
9001 } 9299 }
9002 9300
9003 } } // namespace v8::internal 9301 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698