OLD | NEW |
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 1888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1899 | 1899 |
1900 | 1900 |
1901 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 1901 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
1902 : HGraphBuilder(info), | 1902 : HGraphBuilder(info), |
1903 function_state_(NULL), | 1903 function_state_(NULL), |
1904 initial_function_state_(this, info, NORMAL_RETURN), | 1904 initial_function_state_(this, info, NORMAL_RETURN), |
1905 ast_context_(NULL), | 1905 ast_context_(NULL), |
1906 break_scope_(NULL), | 1906 break_scope_(NULL), |
1907 inlined_count_(0), | 1907 inlined_count_(0), |
1908 globals_(10, info->zone()), | 1908 globals_(10, info->zone()), |
1909 inline_bailout_(false) { | 1909 inline_bailout_(false), |
| 1910 osr_(this) { |
1910 // This is not initialized in the initializer list because the | 1911 // This is not initialized in the initializer list because the |
1911 // constructor for the initial state relies on function_state_ == NULL | 1912 // constructor for the initial state relies on function_state_ == NULL |
1912 // to know it's the initial state. | 1913 // to know it's the initial state. |
1913 function_state_= &initial_function_state_; | 1914 function_state_= &initial_function_state_; |
1914 InitializeAstVisitor(); | 1915 InitializeAstVisitor(); |
1915 } | 1916 } |
1916 | 1917 |
1917 | 1918 |
1918 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 1919 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
1919 HBasicBlock* second, | 1920 HBasicBlock* second, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1967 | 1968 |
1968 | 1969 |
1969 HGraph::HGraph(CompilationInfo* info) | 1970 HGraph::HGraph(CompilationInfo* info) |
1970 : isolate_(info->isolate()), | 1971 : isolate_(info->isolate()), |
1971 next_block_id_(0), | 1972 next_block_id_(0), |
1972 entry_block_(NULL), | 1973 entry_block_(NULL), |
1973 blocks_(8, info->zone()), | 1974 blocks_(8, info->zone()), |
1974 values_(16, info->zone()), | 1975 values_(16, info->zone()), |
1975 phi_list_(NULL), | 1976 phi_list_(NULL), |
1976 uint32_instructions_(NULL), | 1977 uint32_instructions_(NULL), |
| 1978 osr_(NULL), |
1977 info_(info), | 1979 info_(info), |
1978 zone_(info->zone()), | 1980 zone_(info->zone()), |
1979 is_recursive_(false), | 1981 is_recursive_(false), |
1980 use_optimistic_licm_(false), | 1982 use_optimistic_licm_(false), |
1981 has_soft_deoptimize_(false), | 1983 has_soft_deoptimize_(false), |
1982 depends_on_empty_array_proto_elements_(false), | 1984 depends_on_empty_array_proto_elements_(false), |
1983 type_change_checksum_(0), | 1985 type_change_checksum_(0), |
1984 maximum_environment_size_(0) { | 1986 maximum_environment_size_(0) { |
1985 if (info->IsStub()) { | 1987 if (info->IsStub()) { |
1986 HydrogenCodeStub* stub = info->code_stub(); | 1988 HydrogenCodeStub* stub = info->code_stub(); |
(...skipping 1751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3738 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 3740 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
3739 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3741 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
3740 Handle<TypeFeedbackInfo> type_info( | 3742 Handle<TypeFeedbackInfo> type_info( |
3741 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3743 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
3742 int checksum = type_info->own_type_change_checksum(); | 3744 int checksum = type_info->own_type_change_checksum(); |
3743 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3745 int composite_checksum = graph()->update_type_change_checksum(checksum); |
3744 graph()->set_use_optimistic_licm( | 3746 graph()->set_use_optimistic_licm( |
3745 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3747 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
3746 type_info->set_inlined_type_change_checksum(composite_checksum); | 3748 type_info->set_inlined_type_change_checksum(composite_checksum); |
3747 | 3749 |
| 3750 // Perform any necessary OSR-specific cleanups or changes to the graph. |
| 3751 osr_.FinishGraph(); |
| 3752 |
3748 return true; | 3753 return true; |
3749 } | 3754 } |
3750 | 3755 |
3751 | 3756 |
3752 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3757 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
3753 *bailout_reason = SmartArrayPointer<char>(); | 3758 *bailout_reason = SmartArrayPointer<char>(); |
3754 OrderBlocks(); | 3759 OrderBlocks(); |
3755 AssignDominators(); | 3760 AssignDominators(); |
3756 | 3761 |
3757 // We need to create a HConstant "zero" now so that GVN will fold every | 3762 // We need to create a HConstant "zero" now so that GVN will fold every |
(...skipping 23 matching lines...) Expand all Loading... |
3781 "Unsupported phi use of arguments")); | 3786 "Unsupported phi use of arguments")); |
3782 return false; | 3787 return false; |
3783 } | 3788 } |
3784 | 3789 |
3785 // Remove dead code and phis | 3790 // Remove dead code and phis |
3786 if (FLAG_dead_code_elimination) { | 3791 if (FLAG_dead_code_elimination) { |
3787 DeadCodeElimination("H_Eliminate early dead code"); | 3792 DeadCodeElimination("H_Eliminate early dead code"); |
3788 } | 3793 } |
3789 CollectPhis(); | 3794 CollectPhis(); |
3790 | 3795 |
3791 if (has_osr_loop_entry()) { | 3796 if (has_osr()) osr()->FinishOsrValues(); |
3792 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis(); | |
3793 for (int j = 0; j < phis->length(); j++) { | |
3794 HPhi* phi = phis->at(j); | |
3795 osr_values()->at(phi->merged_index())->set_incoming_value(phi); | |
3796 } | |
3797 } | |
3798 | 3797 |
3799 Run<HInferRepresentationPhase>(); | 3798 Run<HInferRepresentationPhase>(); |
3800 | 3799 |
3801 // Remove HSimulate instructions that have turned out not to be needed | 3800 // Remove HSimulate instructions that have turned out not to be needed |
3802 // after all by folding them into the following HSimulate. | 3801 // after all by folding them into the following HSimulate. |
3803 // This must happen after inferring representations. | 3802 // This must happen after inferring representations. |
3804 MergeRemovableSimulates(); | 3803 MergeRemovableSimulates(); |
3805 | 3804 |
3806 MarkDeoptimizeOnUndefined(); | 3805 MarkDeoptimizeOnUndefined(); |
3807 InsertRepresentationChanges(); | 3806 InsertRepresentationChanges(); |
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4895 stmt->ExitId())); | 4894 stmt->ExitId())); |
4896 } else { | 4895 } else { |
4897 if (fall_through_block != NULL) fall_through_block->Goto(break_block); | 4896 if (fall_through_block != NULL) fall_through_block->Goto(break_block); |
4898 if (last_block != NULL) last_block->Goto(break_block); | 4897 if (last_block != NULL) last_block->Goto(break_block); |
4899 break_block->SetJoinId(stmt->ExitId()); | 4898 break_block->SetJoinId(stmt->ExitId()); |
4900 set_current_block(break_block); | 4899 set_current_block(break_block); |
4901 } | 4900 } |
4902 } | 4901 } |
4903 | 4902 |
4904 | 4903 |
4905 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { | |
4906 return statement->OsrEntryId() == current_info()->osr_ast_id(); | |
4907 } | |
4908 | |
4909 | |
4910 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | |
4911 if (!HasOsrEntryAt(statement)) return false; | |
4912 | |
4913 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | |
4914 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | |
4915 HValue* true_value = graph()->GetConstantTrue(); | |
4916 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); | |
4917 current_block()->Finish(test); | |
4918 | |
4919 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | |
4920 non_osr_entry->Goto(loop_predecessor); | |
4921 | |
4922 set_current_block(osr_entry); | |
4923 osr_entry->set_osr_entry(); | |
4924 BailoutId osr_entry_id = statement->OsrEntryId(); | |
4925 int first_expression_index = environment()->first_expression_index(); | |
4926 int length = environment()->length(); | |
4927 ZoneList<HUnknownOSRValue*>* osr_values = | |
4928 new(zone()) ZoneList<HUnknownOSRValue*>(length, zone()); | |
4929 | |
4930 for (int i = 0; i < first_expression_index; ++i) { | |
4931 HUnknownOSRValue* osr_value = Add<HUnknownOSRValue>(); | |
4932 environment()->Bind(i, osr_value); | |
4933 osr_values->Add(osr_value, zone()); | |
4934 } | |
4935 | |
4936 if (first_expression_index != length) { | |
4937 environment()->Drop(length - first_expression_index); | |
4938 for (int i = first_expression_index; i < length; ++i) { | |
4939 HUnknownOSRValue* osr_value = Add<HUnknownOSRValue>(); | |
4940 environment()->Push(osr_value); | |
4941 osr_values->Add(osr_value, zone()); | |
4942 } | |
4943 } | |
4944 | |
4945 graph()->set_osr_values(osr_values); | |
4946 | |
4947 AddSimulate(osr_entry_id); | |
4948 Add<HOsrEntry>(osr_entry_id); | |
4949 HContext* context = Add<HContext>(); | |
4950 environment()->BindContext(context); | |
4951 current_block()->Goto(loop_predecessor); | |
4952 loop_predecessor->SetJoinId(statement->EntryId()); | |
4953 set_current_block(loop_predecessor); | |
4954 return true; | |
4955 } | |
4956 | |
4957 | |
4958 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4904 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
4959 HBasicBlock* loop_entry, | 4905 HBasicBlock* loop_entry, |
4960 BreakAndContinueInfo* break_info) { | 4906 BreakAndContinueInfo* break_info) { |
4961 BreakAndContinueScope push(break_info, this); | 4907 BreakAndContinueScope push(break_info, this); |
4962 AddSimulate(stmt->StackCheckId()); | 4908 AddSimulate(stmt->StackCheckId()); |
4963 HValue* context = environment()->LookupContext(); | 4909 HValue* context = environment()->LookupContext(); |
4964 HStackCheck* stack_check = Add<HStackCheck>( | 4910 HStackCheck* stack_check = Add<HStackCheck>( |
4965 context, HStackCheck::kBackwardsBranch); | 4911 context, HStackCheck::kBackwardsBranch); |
4966 ASSERT(loop_entry->IsLoopHeader()); | 4912 ASSERT(loop_entry->IsLoopHeader()); |
4967 loop_entry->loop_information()->set_stack_check(stack_check); | 4913 loop_entry->loop_information()->set_stack_check(stack_check); |
4968 CHECK_BAILOUT(Visit(stmt->body())); | 4914 CHECK_BAILOUT(Visit(stmt->body())); |
4969 } | 4915 } |
4970 | 4916 |
4971 | 4917 |
4972 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4918 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
4973 ASSERT(!HasStackOverflow()); | 4919 ASSERT(!HasStackOverflow()); |
4974 ASSERT(current_block() != NULL); | 4920 ASSERT(current_block() != NULL); |
4975 ASSERT(current_block()->HasPredecessor()); | 4921 ASSERT(current_block()->HasPredecessor()); |
4976 ASSERT(current_block() != NULL); | 4922 ASSERT(current_block() != NULL); |
4977 bool osr_entry = PreProcessOsrEntry(stmt); | 4923 HBasicBlock* loop_entry = osr_.BuildPossibleOsrLoopEntry(stmt); |
4978 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
4979 current_block()->Goto(loop_entry); | |
4980 set_current_block(loop_entry); | |
4981 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
4982 | 4924 |
4983 BreakAndContinueInfo break_info(stmt); | 4925 BreakAndContinueInfo break_info(stmt); |
4984 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 4926 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
4985 HBasicBlock* body_exit = | 4927 HBasicBlock* body_exit = |
4986 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4928 JoinContinue(stmt, current_block(), break_info.continue_block()); |
4987 HBasicBlock* loop_successor = NULL; | 4929 HBasicBlock* loop_successor = NULL; |
4988 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 4930 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
4989 set_current_block(body_exit); | 4931 set_current_block(body_exit); |
4990 // The block for a true condition, the actual predecessor block of the | 4932 // The block for a true condition, the actual predecessor block of the |
4991 // back edge. | 4933 // back edge. |
(...skipping 18 matching lines...) Expand all Loading... |
5010 break_info.break_block()); | 4952 break_info.break_block()); |
5011 set_current_block(loop_exit); | 4953 set_current_block(loop_exit); |
5012 } | 4954 } |
5013 | 4955 |
5014 | 4956 |
5015 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4957 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
5016 ASSERT(!HasStackOverflow()); | 4958 ASSERT(!HasStackOverflow()); |
5017 ASSERT(current_block() != NULL); | 4959 ASSERT(current_block() != NULL); |
5018 ASSERT(current_block()->HasPredecessor()); | 4960 ASSERT(current_block()->HasPredecessor()); |
5019 ASSERT(current_block() != NULL); | 4961 ASSERT(current_block() != NULL); |
5020 bool osr_entry = PreProcessOsrEntry(stmt); | 4962 HBasicBlock* loop_entry = osr_.BuildPossibleOsrLoopEntry(stmt); |
5021 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
5022 current_block()->Goto(loop_entry); | |
5023 set_current_block(loop_entry); | |
5024 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
5025 | |
5026 | 4963 |
5027 // If the condition is constant true, do not generate a branch. | 4964 // If the condition is constant true, do not generate a branch. |
5028 HBasicBlock* loop_successor = NULL; | 4965 HBasicBlock* loop_successor = NULL; |
5029 if (!stmt->cond()->ToBooleanIsTrue()) { | 4966 if (!stmt->cond()->ToBooleanIsTrue()) { |
5030 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 4967 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
5031 loop_successor = graph()->CreateBasicBlock(); | 4968 loop_successor = graph()->CreateBasicBlock(); |
5032 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 4969 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
5033 if (body_entry->HasPredecessor()) { | 4970 if (body_entry->HasPredecessor()) { |
5034 body_entry->SetJoinId(stmt->BodyId()); | 4971 body_entry->SetJoinId(stmt->BodyId()); |
5035 set_current_block(body_entry); | 4972 set_current_block(body_entry); |
(...skipping 21 matching lines...) Expand all Loading... |
5057 | 4994 |
5058 | 4995 |
5059 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 4996 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { |
5060 ASSERT(!HasStackOverflow()); | 4997 ASSERT(!HasStackOverflow()); |
5061 ASSERT(current_block() != NULL); | 4998 ASSERT(current_block() != NULL); |
5062 ASSERT(current_block()->HasPredecessor()); | 4999 ASSERT(current_block()->HasPredecessor()); |
5063 if (stmt->init() != NULL) { | 5000 if (stmt->init() != NULL) { |
5064 CHECK_ALIVE(Visit(stmt->init())); | 5001 CHECK_ALIVE(Visit(stmt->init())); |
5065 } | 5002 } |
5066 ASSERT(current_block() != NULL); | 5003 ASSERT(current_block() != NULL); |
5067 bool osr_entry = PreProcessOsrEntry(stmt); | 5004 HBasicBlock* loop_entry = osr_.BuildPossibleOsrLoopEntry(stmt); |
5068 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
5069 current_block()->Goto(loop_entry); | |
5070 set_current_block(loop_entry); | |
5071 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
5072 | 5005 |
5073 HBasicBlock* loop_successor = NULL; | 5006 HBasicBlock* loop_successor = NULL; |
5074 if (stmt->cond() != NULL) { | 5007 if (stmt->cond() != NULL) { |
5075 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 5008 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
5076 loop_successor = graph()->CreateBasicBlock(); | 5009 loop_successor = graph()->CreateBasicBlock(); |
5077 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 5010 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
5078 if (body_entry->HasPredecessor()) { | 5011 if (body_entry->HasPredecessor()) { |
5079 body_entry->SetJoinId(stmt->BodyId()); | 5012 body_entry->SetJoinId(stmt->BodyId()); |
5080 set_current_block(body_entry); | 5013 set_current_block(body_entry); |
5081 } | 5014 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5145 Push(map); | 5078 Push(map); |
5146 Push(array); | 5079 Push(array); |
5147 Push(enum_length); | 5080 Push(enum_length); |
5148 Push(start_index); | 5081 Push(start_index); |
5149 | 5082 |
5150 HInstruction* index_cache = Add<HForInCacheArray>( | 5083 HInstruction* index_cache = Add<HForInCacheArray>( |
5151 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); | 5084 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
5152 HForInCacheArray::cast(array)->set_index_cache( | 5085 HForInCacheArray::cast(array)->set_index_cache( |
5153 HForInCacheArray::cast(index_cache)); | 5086 HForInCacheArray::cast(index_cache)); |
5154 | 5087 |
5155 bool osr_entry = PreProcessOsrEntry(stmt); | 5088 HBasicBlock* loop_entry = osr_.BuildPossibleOsrLoopEntry(stmt); |
5156 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | |
5157 current_block()->Goto(loop_entry); | |
5158 set_current_block(loop_entry); | |
5159 if (osr_entry) graph()->set_osr_loop_entry(loop_entry); | |
5160 | 5089 |
5161 HValue* index = environment()->ExpressionStackAt(0); | 5090 HValue* index = environment()->ExpressionStackAt(0); |
5162 HValue* limit = environment()->ExpressionStackAt(1); | 5091 HValue* limit = environment()->ExpressionStackAt(1); |
5163 | 5092 |
5164 // Check that we still have more keys. | 5093 // Check that we still have more keys. |
5165 HCompareIDAndBranch* compare_index = | 5094 HCompareIDAndBranch* compare_index = |
5166 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); | 5095 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); |
5167 compare_index->set_observed_input_representation( | 5096 compare_index->set_observed_input_representation( |
5168 Representation::Smi(), Representation::Smi()); | 5097 Representation::Smi(), Representation::Smi()); |
5169 | 5098 |
(...skipping 6071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11241 if (ShouldProduceTraceOutput()) { | 11170 if (ShouldProduceTraceOutput()) { |
11242 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11171 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11243 } | 11172 } |
11244 | 11173 |
11245 #ifdef DEBUG | 11174 #ifdef DEBUG |
11246 graph_->Verify(false); // No full verify. | 11175 graph_->Verify(false); // No full verify. |
11247 #endif | 11176 #endif |
11248 } | 11177 } |
11249 | 11178 |
11250 } } // namespace v8::internal | 11179 } } // namespace v8::internal |
OLD | NEW |