OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 if (IsConstantFalse(constant)) return true; | 738 if (IsConstantFalse(constant)) return true; |
739 if (IsConstantHole(constant)) return true; | 739 if (IsConstantHole(constant)) return true; |
740 if (IsConstantNull(constant)) return true; | 740 if (IsConstantNull(constant)) return true; |
741 return false; | 741 return false; |
742 } | 742 } |
743 | 743 |
744 | 744 |
745 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) | 745 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder) |
746 : builder_(builder), | 746 : builder_(builder), |
747 finished_(false), | 747 finished_(false), |
748 deopt_then_(false), | |
749 deopt_else_(false), | |
750 did_then_(false), | 748 did_then_(false), |
751 did_else_(false), | 749 did_else_(false), |
750 did_else_if_(false), | |
752 did_and_(false), | 751 did_and_(false), |
753 did_or_(false), | 752 did_or_(false), |
754 captured_(false), | 753 captured_(false), |
755 needs_compare_(true), | 754 needs_compare_(true), |
755 pending_merge_block_(false), | |
756 split_edge_merge_block_(NULL), | 756 split_edge_merge_block_(NULL), |
757 merge_block_(NULL) { | 757 merge_at_join_blocks_(NULL), |
758 normal_merge_at_join_block_count_(0), | |
759 deopt_merge_at_join_block_count_(0) { | |
758 HEnvironment* env = builder->environment(); | 760 HEnvironment* env = builder->environment(); |
759 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 761 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
760 last_true_block_ = NULL; | |
761 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 762 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
762 } | 763 } |
763 | 764 |
764 | 765 |
765 HGraphBuilder::IfBuilder::IfBuilder( | 766 HGraphBuilder::IfBuilder::IfBuilder( |
766 HGraphBuilder* builder, | 767 HGraphBuilder* builder, |
767 HIfContinuation* continuation) | 768 HIfContinuation* continuation) |
768 : builder_(builder), | 769 : builder_(builder), |
769 finished_(false), | 770 finished_(false), |
770 deopt_then_(false), | |
771 deopt_else_(false), | |
772 did_then_(false), | 771 did_then_(false), |
773 did_else_(false), | 772 did_else_(false), |
773 did_else_if_(false), | |
774 did_and_(false), | 774 did_and_(false), |
775 did_or_(false), | 775 did_or_(false), |
776 captured_(false), | 776 captured_(false), |
777 needs_compare_(false), | 777 needs_compare_(false), |
778 pending_merge_block_(false), | |
778 first_true_block_(NULL), | 779 first_true_block_(NULL), |
779 last_true_block_(NULL), | |
780 first_false_block_(NULL), | 780 first_false_block_(NULL), |
781 split_edge_merge_block_(NULL), | 781 split_edge_merge_block_(NULL), |
782 merge_block_(NULL) { | 782 merge_at_join_blocks_(NULL), |
783 normal_merge_at_join_block_count_(0), | |
784 deopt_merge_at_join_block_count_(0) { | |
783 continuation->Continue(&first_true_block_, | 785 continuation->Continue(&first_true_block_, |
784 &first_false_block_); | 786 &first_false_block_); |
785 } | 787 } |
786 | 788 |
787 | 789 |
788 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( | 790 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
789 HControlInstruction* compare) { | 791 HControlInstruction* compare) { |
792 ASSERT(did_then_ == did_else_); | |
793 if (did_else_) { | |
794 // Handle if-then-elseif | |
795 did_else_if_ = true; | |
796 did_else_ = false; | |
797 did_then_ = false; | |
798 did_and_ = false; | |
799 did_or_ = false; | |
800 pending_merge_block_ = false; | |
801 split_edge_merge_block_ = NULL; | |
802 HEnvironment* env = builder_->environment(); | |
803 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); | |
804 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); | |
805 } | |
790 if (split_edge_merge_block_ != NULL) { | 806 if (split_edge_merge_block_ != NULL) { |
791 HEnvironment* env = first_false_block_->last_environment(); | 807 HEnvironment* env = first_false_block_->last_environment(); |
792 HBasicBlock* split_edge = | 808 HBasicBlock* split_edge = |
793 builder_->CreateBasicBlock(env->Copy()); | 809 builder_->CreateBasicBlock(env->Copy()); |
794 if (did_or_) { | 810 if (did_or_) { |
795 compare->SetSuccessorAt(0, split_edge); | 811 compare->SetSuccessorAt(0, split_edge); |
796 compare->SetSuccessorAt(1, first_false_block_); | 812 compare->SetSuccessorAt(1, first_false_block_); |
797 } else { | 813 } else { |
798 compare->SetSuccessorAt(0, first_true_block_); | 814 compare->SetSuccessorAt(0, first_true_block_); |
799 compare->SetSuccessorAt(1, split_edge); | 815 compare->SetSuccessorAt(1, split_edge); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
835 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); | 851 builder_->GotoNoSimulate(first_false_block_, split_edge_merge_block_); |
836 first_false_block_ = split_edge_merge_block_; | 852 first_false_block_ = split_edge_merge_block_; |
837 } | 853 } |
838 builder_->set_current_block(first_true_block_); | 854 builder_->set_current_block(first_true_block_); |
839 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); | 855 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); |
840 } | 856 } |
841 | 857 |
842 | 858 |
843 void HGraphBuilder::IfBuilder::CaptureContinuation( | 859 void HGraphBuilder::IfBuilder::CaptureContinuation( |
844 HIfContinuation* continuation) { | 860 HIfContinuation* continuation) { |
861 ASSERT(!did_else_if_); | |
845 ASSERT(!finished_); | 862 ASSERT(!finished_); |
846 ASSERT(!captured_); | 863 ASSERT(!captured_); |
847 HBasicBlock* true_block = last_true_block_ == NULL | 864 |
848 ? first_true_block_ | 865 HBasicBlock* true_block = NULL; |
849 : last_true_block_; | 866 HBasicBlock* false_block = NULL; |
850 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 867 Finish(&true_block, &false_block); |
851 ? builder_->current_block() | 868 ASSERT(true_block != NULL); |
852 : first_false_block_; | 869 ASSERT(false_block != NULL); |
853 continuation->Capture(true_block, false_block); | 870 continuation->Capture(true_block, false_block); |
854 captured_ = true; | 871 captured_ = true; |
855 End(); | 872 End(); |
856 } | 873 } |
857 | 874 |
858 | 875 |
859 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { | 876 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
877 ASSERT(!did_else_if_); | |
860 ASSERT(!finished_); | 878 ASSERT(!finished_); |
861 ASSERT(!captured_); | 879 ASSERT(!captured_); |
862 ASSERT(did_then_); | 880 HBasicBlock* true_block = NULL; |
863 if (!did_else_) Else(); | 881 HBasicBlock* false_block = NULL; |
864 HBasicBlock* true_block = last_true_block_ == NULL | 882 Finish(&true_block, &false_block); |
865 ? first_true_block_ | 883 merge_at_join_blocks_ = NULL; |
866 : last_true_block_; | |
867 HBasicBlock* false_block = builder_->current_block(); | |
868 if (true_block != NULL && !true_block->IsFinished()) { | 884 if (true_block != NULL && !true_block->IsFinished()) { |
869 ASSERT(continuation->IsTrueReachable()); | 885 ASSERT(continuation->IsTrueReachable()); |
870 builder_->GotoNoSimulate(true_block, continuation->true_branch()); | 886 builder_->GotoNoSimulate(true_block, continuation->true_branch()); |
871 } | 887 } |
872 if (false_block != NULL && !false_block->IsFinished()) { | 888 if (false_block != NULL && !false_block->IsFinished()) { |
873 ASSERT(continuation->IsFalseReachable()); | 889 ASSERT(continuation->IsFalseReachable()); |
874 builder_->GotoNoSimulate(false_block, continuation->false_branch()); | 890 builder_->GotoNoSimulate(false_block, continuation->false_branch()); |
875 } | 891 } |
876 captured_ = true; | 892 captured_ = true; |
877 End(); | 893 End(); |
(...skipping 10 matching lines...) Expand all Loading... | |
888 // so that the graph builder visits it and sees any live range extending | 904 // so that the graph builder visits it and sees any live range extending |
889 // constructs within it. | 905 // constructs within it. |
890 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 906 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
891 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); | 907 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
892 boolean_type.Add(ToBooleanStub::BOOLEAN); | 908 boolean_type.Add(ToBooleanStub::BOOLEAN); |
893 HBranch* branch = builder()->New<HBranch>( | 909 HBranch* branch = builder()->New<HBranch>( |
894 constant_false, boolean_type, first_true_block_, first_false_block_); | 910 constant_false, boolean_type, first_true_block_, first_false_block_); |
895 builder_->FinishCurrentBlock(branch); | 911 builder_->FinishCurrentBlock(branch); |
896 } | 912 } |
897 builder_->set_current_block(first_true_block_); | 913 builder_->set_current_block(first_true_block_); |
914 pending_merge_block_ = true; | |
898 } | 915 } |
899 | 916 |
900 | 917 |
901 void HGraphBuilder::IfBuilder::Else() { | 918 void HGraphBuilder::IfBuilder::Else() { |
902 ASSERT(did_then_); | 919 ASSERT(did_then_); |
903 ASSERT(!captured_); | 920 ASSERT(!captured_); |
904 ASSERT(!finished_); | 921 ASSERT(!finished_); |
905 last_true_block_ = builder_->current_block(); | 922 AddMergeAtJoinBlock(false); |
906 builder_->set_current_block(first_false_block_); | 923 builder_->set_current_block(first_false_block_); |
924 pending_merge_block_ = true; | |
907 did_else_ = true; | 925 did_else_ = true; |
908 } | 926 } |
909 | 927 |
910 | 928 |
911 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 929 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
912 ASSERT(did_then_); | 930 ASSERT(did_then_); |
913 if (did_else_) { | |
914 deopt_else_ = true; | |
915 } else { | |
916 deopt_then_ = true; | |
917 } | |
918 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 931 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
932 AddMergeAtJoinBlock(true); | |
919 } | 933 } |
920 | 934 |
921 | 935 |
922 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 936 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
923 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 937 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
924 builder_->FinishExitCurrentBlock( | 938 builder_->FinishExitCurrentBlock( |
925 builder_->New<HReturn>(value, parameter_count)); | 939 builder_->New<HReturn>(value, parameter_count)); |
926 if (did_else_) { | 940 AddMergeAtJoinBlock(false); |
927 first_false_block_ = NULL; | |
928 } else { | |
929 first_true_block_ = NULL; | |
930 } | |
931 } | 941 } |
932 | 942 |
933 | 943 |
934 void HGraphBuilder::IfBuilder::End() { | 944 void HGraphBuilder::IfBuilder::Finish() { |
935 if (!captured_) { | 945 ASSERT(!finished_); |
936 ASSERT(did_then_); | 946 if (!did_then_) { |
937 if (!did_else_) { | 947 Then(); |
938 last_true_block_ = builder_->current_block(); | 948 } |
939 } | 949 AddMergeAtJoinBlock(false); |
940 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { | 950 if (!did_else_) { |
941 ASSERT(did_else_); | 951 Else(); |
942 // Return on true. Nothing to do, just continue the false block. | 952 AddMergeAtJoinBlock(false); |
943 } else if (first_false_block_ == NULL || | |
944 (did_else_ && builder_->current_block()->IsFinished())) { | |
945 // Deopt on false. Nothing to do except switching to the true block. | |
946 builder_->set_current_block(last_true_block_); | |
947 } else { | |
948 merge_block_ = builder_->graph()->CreateBasicBlock(); | |
949 ASSERT(!finished_); | |
950 if (!did_else_) Else(); | |
951 ASSERT(!last_true_block_->IsFinished()); | |
952 HBasicBlock* last_false_block = builder_->current_block(); | |
953 ASSERT(!last_false_block->IsFinished()); | |
954 if (deopt_then_) { | |
955 builder_->GotoNoSimulate(last_false_block, merge_block_); | |
956 builder_->PadEnvironmentForContinuation(last_true_block_, | |
957 merge_block_); | |
958 builder_->GotoNoSimulate(last_true_block_, merge_block_); | |
959 } else { | |
960 builder_->GotoNoSimulate(last_true_block_, merge_block_); | |
961 if (deopt_else_) { | |
962 builder_->PadEnvironmentForContinuation(last_false_block, | |
963 merge_block_); | |
964 } | |
965 builder_->GotoNoSimulate(last_false_block, merge_block_); | |
966 } | |
967 builder_->set_current_block(merge_block_); | |
968 } | |
969 } | 953 } |
970 finished_ = true; | 954 finished_ = true; |
971 } | 955 } |
972 | 956 |
973 | 957 |
958 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation, | |
959 HBasicBlock** else_continuation) { | |
960 Finish(); | |
961 | |
962 MergeAtJoinBlock* else_record = merge_at_join_blocks_; | |
963 if (else_continuation != NULL) { | |
964 *else_continuation = else_record->block_; | |
965 } | |
966 MergeAtJoinBlock* then_record = else_record->next_; | |
967 if (then_continuation != NULL) { | |
968 *then_continuation = then_record->block_; | |
969 } | |
970 ASSERT(then_record->next_ == NULL); | |
971 } | |
972 | |
973 | |
974 void HGraphBuilder::IfBuilder::End() { | |
975 if (captured_) return; | |
976 Finish(); | |
977 | |
978 int total_merged_blocks = normal_merge_at_join_block_count_ + | |
979 deopt_merge_at_join_block_count_; | |
980 ASSERT(total_merged_blocks >= 1); | |
981 HBasicBlock* merge_block = total_merged_blocks == 1 | |
982 ? NULL : builder_->graph()->CreateBasicBlock(); | |
983 | |
984 // Merge non-deopt blocks first to ensure environment has right size for | |
985 // padding. | |
986 MergeAtJoinBlock* current = merge_at_join_blocks_; | |
987 while (current != NULL) { | |
988 if (!current->deopt_ && current->block_ != NULL) { | |
989 // If there is only one block that makes it through to the end of the | |
990 // if, then just set it as the current block and continue rather then | |
991 // creating an unnecessary merge block. | |
992 if (total_merged_blocks == 1) { | |
993 builder_->set_current_block(current->block_); | |
994 return; | |
995 } | |
996 builder_->GotoNoSimulate(current->block_, merge_block); | |
997 } | |
998 current = current->next_; | |
999 } | |
1000 | |
1001 // Merge deopt blocks, padding when necessary. | |
1002 current = merge_at_join_blocks_; | |
1003 while (current != NULL) { | |
1004 if (current->deopt_ && current->block_ != NULL) { | |
1005 builder_->PadEnvironmentForContinuation(current->block_, | |
1006 merge_block); | |
1007 builder_->GotoNoSimulate(current->block_, merge_block); | |
1008 } | |
1009 current = current->next_; | |
1010 } | |
1011 builder_->set_current_block(merge_block); | |
1012 } | |
1013 | |
1014 | |
974 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 1015 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
975 HValue* context, | 1016 HValue* context, |
976 LoopBuilder::Direction direction) | 1017 LoopBuilder::Direction direction) |
977 : builder_(builder), | 1018 : builder_(builder), |
978 context_(context), | 1019 context_(context), |
979 direction_(direction), | 1020 direction_(direction), |
980 finished_(false) { | 1021 finished_(false) { |
981 header_block_ = builder->CreateLoopHeaderBlock(); | 1022 header_block_ = builder->CreateLoopHeaderBlock(); |
982 body_block_ = NULL; | 1023 body_block_ = NULL; |
983 exit_block_ = NULL; | 1024 exit_block_ = NULL; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1044 | 1085 |
1045 void HGraphBuilder::LoopBuilder::Break() { | 1086 void HGraphBuilder::LoopBuilder::Break() { |
1046 if (exit_trampoline_block_ == NULL) { | 1087 if (exit_trampoline_block_ == NULL) { |
1047 // Its the first time we saw a break. | 1088 // Its the first time we saw a break. |
1048 HEnvironment* env = exit_block_->last_environment()->Copy(); | 1089 HEnvironment* env = exit_block_->last_environment()->Copy(); |
1049 exit_trampoline_block_ = builder_->CreateBasicBlock(env); | 1090 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
1050 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); | 1091 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); |
1051 } | 1092 } |
1052 | 1093 |
1053 builder_->GotoNoSimulate(exit_trampoline_block_); | 1094 builder_->GotoNoSimulate(exit_trampoline_block_); |
1095 builder_->set_current_block(NULL); | |
1054 } | 1096 } |
1055 | 1097 |
1056 | 1098 |
1057 void HGraphBuilder::LoopBuilder::EndBody() { | 1099 void HGraphBuilder::LoopBuilder::EndBody() { |
1058 ASSERT(!finished_); | 1100 ASSERT(!finished_); |
1059 | 1101 |
1060 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { | 1102 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { |
1061 if (direction_ == kPostIncrement) { | 1103 if (direction_ == kPostIncrement) { |
1062 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); | 1104 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); |
1063 } else { | 1105 } else { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1112 if (last->IsReturn() || last->IsAbnormalExit()) { | 1154 if (last->IsReturn() || last->IsAbnormalExit()) { |
1113 set_current_block(NULL); | 1155 set_current_block(NULL); |
1114 } | 1156 } |
1115 } | 1157 } |
1116 | 1158 |
1117 | 1159 |
1118 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { | 1160 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
1119 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || | 1161 ASSERT(!FLAG_emit_opt_code_positions || !info_->IsOptimizing() || |
1120 position_ != RelocInfo::kNoPosition); | 1162 position_ != RelocInfo::kNoPosition); |
1121 current_block()->FinishExit(instruction, position_); | 1163 current_block()->FinishExit(instruction, position_); |
1122 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { | 1164 set_current_block(NULL); |
Michael Starzinger
2013/11/12 09:50:00
This change confuses me. HGraphBuilder::FinishExit
danno
2013/11/14 14:46:40
Done.
| |
1123 set_current_block(NULL); | |
1124 } | |
1125 } | 1165 } |
1126 | 1166 |
1127 | 1167 |
1128 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1168 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
1129 if (FLAG_native_code_counters && counter->Enabled()) { | 1169 if (FLAG_native_code_counters && counter->Enabled()) { |
1130 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1170 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
1131 HValue* old_value = Add<HLoadNamedField>(reference, | 1171 HValue* old_value = Add<HLoadNamedField>(reference, |
1132 HObjectAccess::ForCounter()); | 1172 HObjectAccess::ForCounter()); |
1133 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); | 1173 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
1134 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1174 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
(...skipping 8719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9854 if (ShouldProduceTraceOutput()) { | 9894 if (ShouldProduceTraceOutput()) { |
9855 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9895 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9856 } | 9896 } |
9857 | 9897 |
9858 #ifdef DEBUG | 9898 #ifdef DEBUG |
9859 graph_->Verify(false); // No full verify. | 9899 graph_->Verify(false); // No full verify. |
9860 #endif | 9900 #endif |
9861 } | 9901 } |
9862 | 9902 |
9863 } } // namespace v8::internal | 9903 } } // namespace v8::internal |
OLD | NEW |