OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 void HBasicBlock::Finish(HControlInstruction* end) { | 156 void HBasicBlock::Finish(HControlInstruction* end) { |
157 ASSERT(!IsFinished()); | 157 ASSERT(!IsFinished()); |
158 AddInstruction(end); | 158 AddInstruction(end); |
159 end_ = end; | 159 end_ = end; |
160 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 160 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
161 it.Current()->RegisterPredecessor(this); | 161 it.Current()->RegisterPredecessor(this); |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
165 | 165 |
166 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { | 166 void HBasicBlock::Goto(HBasicBlock* block) { |
167 if (block->IsInlineReturnTarget()) { | 167 if (block->IsInlineReturnTarget()) { |
168 AddInstruction(new(zone()) HLeaveInlined); | 168 AddInstruction(new(zone()) HLeaveInlined); |
169 last_environment_ = last_environment()->outer(); | 169 last_environment_ = last_environment()->outer(); |
170 } | 170 } |
171 AddSimulate(AstNode::kNoNumber); | 171 AddSimulate(AstNode::kNoNumber); |
172 HGoto* instr = new(zone()) HGoto(block); | 172 HGoto* instr = new(zone()) HGoto(block); |
173 instr->set_include_stack_check(include_stack_check); | |
174 Finish(instr); | 173 Finish(instr); |
175 } | 174 } |
176 | 175 |
177 | 176 |
178 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { | 177 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { |
179 ASSERT(target->IsInlineReturnTarget()); | 178 ASSERT(target->IsInlineReturnTarget()); |
180 ASSERT(return_value != NULL); | 179 ASSERT(return_value != NULL); |
181 AddInstruction(new(zone()) HLeaveInlined); | 180 AddInstruction(new(zone()) HLeaveInlined); |
182 last_environment_ = last_environment()->outer(); | 181 last_environment_ = last_environment()->outer(); |
183 last_environment()->Push(return_value); | 182 last_environment()->Push(return_value); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 } | 568 } |
570 return exit_block; | 569 return exit_block; |
571 } | 570 } |
572 | 571 |
573 | 572 |
574 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, | 573 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, |
575 HBasicBlock* loop_entry, | 574 HBasicBlock* loop_entry, |
576 HBasicBlock* body_exit, | 575 HBasicBlock* body_exit, |
577 HBasicBlock* loop_successor, | 576 HBasicBlock* loop_successor, |
578 HBasicBlock* break_block) { | 577 HBasicBlock* break_block) { |
579 if (body_exit != NULL) body_exit->Goto(loop_entry, true); | 578 if (body_exit != NULL) body_exit->Goto(loop_entry); |
580 loop_entry->PostProcessLoopHeader(statement); | 579 loop_entry->PostProcessLoopHeader(statement); |
581 if (break_block != NULL) { | 580 if (break_block != NULL) { |
582 if (loop_successor != NULL) loop_successor->Goto(break_block); | 581 if (loop_successor != NULL) loop_successor->Goto(break_block); |
583 break_block->SetJoinId(statement->ExitId()); | 582 break_block->SetJoinId(statement->ExitId()); |
584 return break_block; | 583 return break_block; |
585 } | 584 } |
586 return loop_successor; | 585 return loop_successor; |
587 } | 586 } |
588 | 587 |
589 | 588 |
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1227 } | 1226 } |
1228 | 1227 |
1229 | 1228 |
1230 class HStackCheckEliminator BASE_EMBEDDED { | 1229 class HStackCheckEliminator BASE_EMBEDDED { |
1231 public: | 1230 public: |
1232 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } | 1231 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } |
1233 | 1232 |
1234 void Process(); | 1233 void Process(); |
1235 | 1234 |
1236 private: | 1235 private: |
1237 void RemoveStackCheck(HBasicBlock* block); | |
1238 | |
1239 HGraph* graph_; | 1236 HGraph* graph_; |
1240 }; | 1237 }; |
1241 | 1238 |
1242 | 1239 |
1243 void HStackCheckEliminator::Process() { | 1240 void HStackCheckEliminator::Process() { |
1244 // For each loop block walk the dominator tree from the backwards branch to | 1241 // For each loop block walk the dominator tree from the backwards branch to |
1245 // the loop header. If a call instruction is encountered the backwards branch | 1242 // the loop header. If a call instruction is encountered the backwards branch |
1246 // is dominated by a call and the stack check in the backwards branch can be | 1243 // is dominated by a call and the stack check in the backwards branch can be |
1247 // removed. | 1244 // removed. |
1248 for (int i = 0; i < graph_->blocks()->length(); i++) { | 1245 for (int i = 0; i < graph_->blocks()->length(); i++) { |
1249 HBasicBlock* block = graph_->blocks()->at(i); | 1246 HBasicBlock* block = graph_->blocks()->at(i); |
1250 if (block->IsLoopHeader()) { | 1247 if (block->IsLoopHeader()) { |
1251 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); | 1248 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); |
1252 HBasicBlock* dominator = back_edge; | 1249 HBasicBlock* dominator = back_edge; |
1253 while (true) { | 1250 while (true) { |
1254 HInstruction* instr = dominator->first(); | 1251 HInstruction* instr = dominator->first(); |
1255 while (instr != NULL) { | 1252 while (instr != NULL) { |
1256 if (instr->IsCall()) { | 1253 if (instr->IsCall()) { |
1257 RemoveStackCheck(back_edge); | 1254 block->loop_information()->stack_check()->Eliminate(); |
1258 break; | 1255 break; |
1259 } | 1256 } |
1260 instr = instr->next(); | 1257 instr = instr->next(); |
1261 } | 1258 } |
1262 | 1259 |
1263 // Done when the loop header is processed. | 1260 // Done when the loop header is processed. |
1264 if (dominator == block) break; | 1261 if (dominator == block) break; |
1265 | 1262 |
1266 // Move up the dominator tree. | 1263 // Move up the dominator tree. |
1267 dominator = dominator->dominator(); | 1264 dominator = dominator->dominator(); |
1268 } | 1265 } |
1269 } | 1266 } |
1270 } | 1267 } |
1271 } | 1268 } |
1272 | 1269 |
1273 | 1270 |
1274 void HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) { | |
1275 HInstruction* instr = block->first(); | |
1276 while (instr != NULL) { | |
1277 if (instr->IsGoto()) { | |
1278 HGoto::cast(instr)->set_include_stack_check(false); | |
1279 return; | |
1280 } | |
1281 instr = instr->next(); | |
1282 } | |
1283 } | |
1284 | |
1285 | |
1286 // Simple sparse set with O(1) add, contains, and clear. | 1271 // Simple sparse set with O(1) add, contains, and clear. |
1287 class SparseSet { | 1272 class SparseSet { |
1288 public: | 1273 public: |
1289 SparseSet(Zone* zone, int capacity) | 1274 SparseSet(Zone* zone, int capacity) |
1290 : capacity_(capacity), | 1275 : capacity_(capacity), |
1291 length_(0), | 1276 length_(0), |
1292 dense_(zone->NewArray<int>(capacity)), | 1277 dense_(zone->NewArray<int>(capacity)), |
1293 sparse_(zone->NewArray<int>(capacity)) { | 1278 sparse_(zone->NewArray<int>(capacity)) { |
1294 #ifndef NVALGRIND | 1279 #ifndef NVALGRIND |
1295 // Initialize the sparse array to make valgrind happy. | 1280 // Initialize the sparse array to make valgrind happy. |
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2129 // branch. | 2114 // branch. |
2130 HGraphBuilder* builder = owner(); | 2115 HGraphBuilder* builder = owner(); |
2131 if (value->CheckFlag(HValue::kIsArguments)) { | 2116 if (value->CheckFlag(HValue::kIsArguments)) { |
2132 builder->Bailout("arguments object value in a test context"); | 2117 builder->Bailout("arguments object value in a test context"); |
2133 } | 2118 } |
2134 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2119 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
2135 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2120 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
2136 HTest* test = new(zone()) HTest(value, empty_true, empty_false); | 2121 HTest* test = new(zone()) HTest(value, empty_true, empty_false); |
2137 builder->current_block()->Finish(test); | 2122 builder->current_block()->Finish(test); |
2138 | 2123 |
2139 empty_true->Goto(if_true(), false); | 2124 empty_true->Goto(if_true()); |
2140 empty_false->Goto(if_false(), false); | 2125 empty_false->Goto(if_false()); |
2141 builder->set_current_block(NULL); | 2126 builder->set_current_block(NULL); |
2142 } | 2127 } |
2143 | 2128 |
2144 | 2129 |
2145 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2130 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
2146 #define CHECK_BAILOUT(call) \ | 2131 #define CHECK_BAILOUT(call) \ |
2147 do { \ | 2132 do { \ |
2148 call; \ | 2133 call; \ |
2149 if (HasStackOverflow()) return; \ | 2134 if (HasStackOverflow()) return; \ |
2150 } while (false) | 2135 } while (false) |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2222 HPhase phase("Block building"); | 2207 HPhase phase("Block building"); |
2223 current_block_ = graph()->entry_block(); | 2208 current_block_ = graph()->entry_block(); |
2224 | 2209 |
2225 Scope* scope = info()->scope(); | 2210 Scope* scope = info()->scope(); |
2226 if (scope->HasIllegalRedeclaration()) { | 2211 if (scope->HasIllegalRedeclaration()) { |
2227 Bailout("function with illegal redeclaration"); | 2212 Bailout("function with illegal redeclaration"); |
2228 return NULL; | 2213 return NULL; |
2229 } | 2214 } |
2230 SetupScope(scope); | 2215 SetupScope(scope); |
2231 VisitDeclarations(scope->declarations()); | 2216 VisitDeclarations(scope->declarations()); |
2232 AddInstruction(new(zone()) HStackCheck()); | 2217 AddInstruction(new(zone()) HStackCheck(HStackCheck::kFunctionEntry)); |
2233 | 2218 |
2234 // Add an edge to the body entry. This is warty: the graph's start | 2219 // Add an edge to the body entry. This is warty: the graph's start |
2235 // environment will be used by the Lithium translation as the initial | 2220 // environment will be used by the Lithium translation as the initial |
2236 // environment on graph entry, but it has now been mutated by the | 2221 // environment on graph entry, but it has now been mutated by the |
2237 // Hydrogen translation of the instructions in the start block. This | 2222 // Hydrogen translation of the instructions in the start block. This |
2238 // environment uses values which have not been defined yet. These | 2223 // environment uses values which have not been defined yet. These |
2239 // Hydrogen instructions will then be replayed by the Lithium | 2224 // Hydrogen instructions will then be replayed by the Lithium |
2240 // translation, so they cannot have an environment effect. The edge to | 2225 // translation, so they cannot have an environment effect. The edge to |
2241 // the body's entry block (along with some special logic for the start | 2226 // the body's entry block (along with some special logic for the start |
2242 // block in HInstruction::InsertAfter) seals the start block from | 2227 // block in HInstruction::InsertAfter) seals the start block from |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2560 } else { | 2545 } else { |
2561 // Return from an inlined function, visit the subexpression in the | 2546 // Return from an inlined function, visit the subexpression in the |
2562 // expression context of the call. | 2547 // expression context of the call. |
2563 if (context->IsTest()) { | 2548 if (context->IsTest()) { |
2564 TestContext* test = TestContext::cast(context); | 2549 TestContext* test = TestContext::cast(context); |
2565 VisitForControl(stmt->expression(), | 2550 VisitForControl(stmt->expression(), |
2566 test->if_true(), | 2551 test->if_true(), |
2567 test->if_false()); | 2552 test->if_false()); |
2568 } else if (context->IsEffect()) { | 2553 } else if (context->IsEffect()) { |
2569 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 2554 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
2570 current_block()->Goto(function_return(), false); | 2555 current_block()->Goto(function_return()); |
2571 } else { | 2556 } else { |
2572 ASSERT(context->IsValue()); | 2557 ASSERT(context->IsValue()); |
2573 CHECK_ALIVE(VisitForValue(stmt->expression())); | 2558 CHECK_ALIVE(VisitForValue(stmt->expression())); |
2574 HValue* return_value = environment()->Pop(); | 2559 HValue* return_value = environment()->Pop(); |
2575 current_block()->AddLeaveInlined(return_value, function_return()); | 2560 current_block()->AddLeaveInlined(return_value, function_return()); |
2576 } | 2561 } |
2577 set_current_block(NULL); | 2562 set_current_block(NULL); |
2578 } | 2563 } |
2579 } | 2564 } |
2580 | 2565 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2751 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); | 2736 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); |
2752 HContext* context = new(zone()) HContext; | 2737 HContext* context = new(zone()) HContext; |
2753 AddInstruction(context); | 2738 AddInstruction(context); |
2754 environment()->BindContext(context); | 2739 environment()->BindContext(context); |
2755 current_block()->Goto(loop_predecessor); | 2740 current_block()->Goto(loop_predecessor); |
2756 loop_predecessor->SetJoinId(statement->EntryId()); | 2741 loop_predecessor->SetJoinId(statement->EntryId()); |
2757 set_current_block(loop_predecessor); | 2742 set_current_block(loop_predecessor); |
2758 } | 2743 } |
2759 | 2744 |
2760 | 2745 |
| 2746 void HGraphBuilder::VisitLoopBody(Statement* body, |
| 2747 HBasicBlock* loop_entry, |
| 2748 BreakAndContinueInfo* break_info) { |
| 2749 BreakAndContinueScope push(break_info, this); |
| 2750 HStackCheck* stack_check = |
| 2751 new(zone()) HStackCheck(HStackCheck::kBackwardsBranch); |
| 2752 AddInstruction(stack_check); |
| 2753 ASSERT(loop_entry->IsLoopHeader()); |
| 2754 loop_entry->loop_information()->set_stack_check(stack_check); |
| 2755 CHECK_BAILOUT(Visit(body)); |
| 2756 } |
| 2757 |
| 2758 |
2761 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2759 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
2762 ASSERT(!HasStackOverflow()); | 2760 ASSERT(!HasStackOverflow()); |
2763 ASSERT(current_block() != NULL); | 2761 ASSERT(current_block() != NULL); |
2764 ASSERT(current_block()->HasPredecessor()); | 2762 ASSERT(current_block()->HasPredecessor()); |
2765 ASSERT(current_block() != NULL); | 2763 ASSERT(current_block() != NULL); |
2766 PreProcessOsrEntry(stmt); | 2764 PreProcessOsrEntry(stmt); |
2767 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2765 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2768 current_block()->Goto(loop_entry, false); | 2766 current_block()->Goto(loop_entry); |
2769 set_current_block(loop_entry); | 2767 set_current_block(loop_entry); |
2770 | 2768 |
2771 BreakAndContinueInfo break_info(stmt); | 2769 BreakAndContinueInfo break_info(stmt); |
2772 { BreakAndContinueScope push(&break_info, this); | 2770 CHECK_BAILOUT(VisitLoopBody(stmt->body(), loop_entry, &break_info)); |
2773 CHECK_BAILOUT(Visit(stmt->body())); | |
2774 } | |
2775 HBasicBlock* body_exit = | 2771 HBasicBlock* body_exit = |
2776 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2772 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2777 HBasicBlock* loop_successor = NULL; | 2773 HBasicBlock* loop_successor = NULL; |
2778 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 2774 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
2779 set_current_block(body_exit); | 2775 set_current_block(body_exit); |
2780 // The block for a true condition, the actual predecessor block of the | 2776 // The block for a true condition, the actual predecessor block of the |
2781 // back edge. | 2777 // back edge. |
2782 body_exit = graph()->CreateBasicBlock(); | 2778 body_exit = graph()->CreateBasicBlock(); |
2783 loop_successor = graph()->CreateBasicBlock(); | 2779 loop_successor = graph()->CreateBasicBlock(); |
2784 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); | 2780 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); |
(...skipping 17 matching lines...) Expand all Loading... |
2802 } | 2798 } |
2803 | 2799 |
2804 | 2800 |
2805 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2801 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
2806 ASSERT(!HasStackOverflow()); | 2802 ASSERT(!HasStackOverflow()); |
2807 ASSERT(current_block() != NULL); | 2803 ASSERT(current_block() != NULL); |
2808 ASSERT(current_block()->HasPredecessor()); | 2804 ASSERT(current_block()->HasPredecessor()); |
2809 ASSERT(current_block() != NULL); | 2805 ASSERT(current_block() != NULL); |
2810 PreProcessOsrEntry(stmt); | 2806 PreProcessOsrEntry(stmt); |
2811 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2807 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2812 current_block()->Goto(loop_entry, false); | 2808 current_block()->Goto(loop_entry); |
2813 set_current_block(loop_entry); | 2809 set_current_block(loop_entry); |
2814 | 2810 |
2815 // If the condition is constant true, do not generate a branch. | 2811 // If the condition is constant true, do not generate a branch. |
2816 HBasicBlock* loop_successor = NULL; | 2812 HBasicBlock* loop_successor = NULL; |
2817 if (!stmt->cond()->ToBooleanIsTrue()) { | 2813 if (!stmt->cond()->ToBooleanIsTrue()) { |
2818 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 2814 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
2819 loop_successor = graph()->CreateBasicBlock(); | 2815 loop_successor = graph()->CreateBasicBlock(); |
2820 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 2816 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
2821 if (body_entry->HasPredecessor()) { | 2817 if (body_entry->HasPredecessor()) { |
2822 body_entry->SetJoinId(stmt->BodyId()); | 2818 body_entry->SetJoinId(stmt->BodyId()); |
2823 set_current_block(body_entry); | 2819 set_current_block(body_entry); |
2824 } | 2820 } |
2825 if (loop_successor->HasPredecessor()) { | 2821 if (loop_successor->HasPredecessor()) { |
2826 loop_successor->SetJoinId(stmt->ExitId()); | 2822 loop_successor->SetJoinId(stmt->ExitId()); |
2827 } else { | 2823 } else { |
2828 loop_successor = NULL; | 2824 loop_successor = NULL; |
2829 } | 2825 } |
2830 } | 2826 } |
2831 | 2827 |
2832 BreakAndContinueInfo break_info(stmt); | 2828 BreakAndContinueInfo break_info(stmt); |
2833 if (current_block() != NULL) { | 2829 if (current_block() != NULL) { |
2834 BreakAndContinueScope push(&break_info, this); | 2830 BreakAndContinueScope push(&break_info, this); |
2835 CHECK_BAILOUT(Visit(stmt->body())); | 2831 CHECK_BAILOUT(VisitLoopBody(stmt->body(), loop_entry, &break_info)); |
2836 } | 2832 } |
2837 HBasicBlock* body_exit = | 2833 HBasicBlock* body_exit = |
2838 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2834 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2839 HBasicBlock* loop_exit = CreateLoop(stmt, | 2835 HBasicBlock* loop_exit = CreateLoop(stmt, |
2840 loop_entry, | 2836 loop_entry, |
2841 body_exit, | 2837 body_exit, |
2842 loop_successor, | 2838 loop_successor, |
2843 break_info.break_block()); | 2839 break_info.break_block()); |
2844 set_current_block(loop_exit); | 2840 set_current_block(loop_exit); |
2845 } | 2841 } |
2846 | 2842 |
2847 | 2843 |
2848 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 2844 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
2849 ASSERT(!HasStackOverflow()); | 2845 ASSERT(!HasStackOverflow()); |
2850 ASSERT(current_block() != NULL); | 2846 ASSERT(current_block() != NULL); |
2851 ASSERT(current_block()->HasPredecessor()); | 2847 ASSERT(current_block()->HasPredecessor()); |
2852 if (stmt->init() != NULL) { | 2848 if (stmt->init() != NULL) { |
2853 CHECK_ALIVE(Visit(stmt->init())); | 2849 CHECK_ALIVE(Visit(stmt->init())); |
2854 } | 2850 } |
2855 ASSERT(current_block() != NULL); | 2851 ASSERT(current_block() != NULL); |
2856 PreProcessOsrEntry(stmt); | 2852 PreProcessOsrEntry(stmt); |
2857 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2853 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
2858 current_block()->Goto(loop_entry, false); | 2854 current_block()->Goto(loop_entry); |
2859 set_current_block(loop_entry); | 2855 set_current_block(loop_entry); |
2860 | 2856 |
2861 HBasicBlock* loop_successor = NULL; | 2857 HBasicBlock* loop_successor = NULL; |
2862 if (stmt->cond() != NULL) { | 2858 if (stmt->cond() != NULL) { |
2863 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 2859 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
2864 loop_successor = graph()->CreateBasicBlock(); | 2860 loop_successor = graph()->CreateBasicBlock(); |
2865 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 2861 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
2866 if (body_entry->HasPredecessor()) { | 2862 if (body_entry->HasPredecessor()) { |
2867 body_entry->SetJoinId(stmt->BodyId()); | 2863 body_entry->SetJoinId(stmt->BodyId()); |
2868 set_current_block(body_entry); | 2864 set_current_block(body_entry); |
2869 } | 2865 } |
2870 if (loop_successor->HasPredecessor()) { | 2866 if (loop_successor->HasPredecessor()) { |
2871 loop_successor->SetJoinId(stmt->ExitId()); | 2867 loop_successor->SetJoinId(stmt->ExitId()); |
2872 } else { | 2868 } else { |
2873 loop_successor = NULL; | 2869 loop_successor = NULL; |
2874 } | 2870 } |
2875 } | 2871 } |
2876 | 2872 |
2877 BreakAndContinueInfo break_info(stmt); | 2873 BreakAndContinueInfo break_info(stmt); |
2878 if (current_block() != NULL) { | 2874 if (current_block() != NULL) { |
2879 BreakAndContinueScope push(&break_info, this); | 2875 BreakAndContinueScope push(&break_info, this); |
2880 CHECK_BAILOUT(Visit(stmt->body())); | 2876 CHECK_BAILOUT(VisitLoopBody(stmt->body(), loop_entry, &break_info)); |
2881 } | 2877 } |
2882 HBasicBlock* body_exit = | 2878 HBasicBlock* body_exit = |
2883 JoinContinue(stmt, current_block(), break_info.continue_block()); | 2879 JoinContinue(stmt, current_block(), break_info.continue_block()); |
2884 | 2880 |
2885 if (stmt->next() != NULL && body_exit != NULL) { | 2881 if (stmt->next() != NULL && body_exit != NULL) { |
2886 set_current_block(body_exit); | 2882 set_current_block(body_exit); |
2887 CHECK_BAILOUT(Visit(stmt->next())); | 2883 CHECK_BAILOUT(Visit(stmt->next())); |
2888 body_exit = current_block(); | 2884 body_exit = current_block(); |
2889 } | 2885 } |
2890 | 2886 |
(...skipping 1588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4479 | 4475 |
4480 TraceInline(target, caller, NULL); | 4476 TraceInline(target, caller, NULL); |
4481 | 4477 |
4482 if (current_block() != NULL) { | 4478 if (current_block() != NULL) { |
4483 // Add a return of undefined if control can fall off the body. In a | 4479 // Add a return of undefined if control can fall off the body. In a |
4484 // test context, undefined is false. | 4480 // test context, undefined is false. |
4485 if (inlined_test_context() == NULL) { | 4481 if (inlined_test_context() == NULL) { |
4486 ASSERT(function_return() != NULL); | 4482 ASSERT(function_return() != NULL); |
4487 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); | 4483 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); |
4488 if (call_context()->IsEffect()) { | 4484 if (call_context()->IsEffect()) { |
4489 current_block()->Goto(function_return(), false); | 4485 current_block()->Goto(function_return()); |
4490 } else { | 4486 } else { |
4491 current_block()->AddLeaveInlined(undefined, function_return()); | 4487 current_block()->AddLeaveInlined(undefined, function_return()); |
4492 } | 4488 } |
4493 } else { | 4489 } else { |
4494 // The graph builder assumes control can reach both branches of a | 4490 // The graph builder assumes control can reach both branches of a |
4495 // test, so we materialize the undefined value and test it rather than | 4491 // test, so we materialize the undefined value and test it rather than |
4496 // simply jumping to the false target. | 4492 // simply jumping to the false target. |
4497 // | 4493 // |
4498 // TODO(3168478): refactor to avoid this. | 4494 // TODO(3168478): refactor to avoid this. |
4499 HBasicBlock* empty_true = graph()->CreateBasicBlock(); | 4495 HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
4500 HBasicBlock* empty_false = graph()->CreateBasicBlock(); | 4496 HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
4501 HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); | 4497 HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); |
4502 current_block()->Finish(test); | 4498 current_block()->Finish(test); |
4503 | 4499 |
4504 empty_true->Goto(inlined_test_context()->if_true(), false); | 4500 empty_true->Goto(inlined_test_context()->if_true()); |
4505 empty_false->Goto(inlined_test_context()->if_false(), false); | 4501 empty_false->Goto(inlined_test_context()->if_false()); |
4506 } | 4502 } |
4507 } | 4503 } |
4508 | 4504 |
4509 // Fix up the function exits. | 4505 // Fix up the function exits. |
4510 if (inlined_test_context() != NULL) { | 4506 if (inlined_test_context() != NULL) { |
4511 HBasicBlock* if_true = inlined_test_context()->if_true(); | 4507 HBasicBlock* if_true = inlined_test_context()->if_true(); |
4512 HBasicBlock* if_false = inlined_test_context()->if_false(); | 4508 HBasicBlock* if_false = inlined_test_context()->if_false(); |
4513 | 4509 |
4514 // Pop the return test context from the expression context stack. | 4510 // Pop the return test context from the expression context stack. |
4515 ASSERT(ast_context() == inlined_test_context()); | 4511 ASSERT(ast_context() == inlined_test_context()); |
4516 ClearInlinedTestContext(); | 4512 ClearInlinedTestContext(); |
4517 | 4513 |
4518 // Forward to the real test context. | 4514 // Forward to the real test context. |
4519 if (if_true->HasPredecessor()) { | 4515 if (if_true->HasPredecessor()) { |
4520 if_true->SetJoinId(expr->id()); | 4516 if_true->SetJoinId(expr->id()); |
4521 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 4517 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
4522 if_true->Goto(true_target, false); | 4518 if_true->Goto(true_target); |
4523 } | 4519 } |
4524 if (if_false->HasPredecessor()) { | 4520 if (if_false->HasPredecessor()) { |
4525 if_false->SetJoinId(expr->id()); | 4521 if_false->SetJoinId(expr->id()); |
4526 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); | 4522 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); |
4527 if_false->Goto(false_target, false); | 4523 if_false->Goto(false_target); |
4528 } | 4524 } |
4529 set_current_block(NULL); | 4525 set_current_block(NULL); |
4530 | 4526 |
4531 } else if (function_return()->HasPredecessor()) { | 4527 } else if (function_return()->HasPredecessor()) { |
4532 function_return()->SetJoinId(expr->id()); | 4528 function_return()->SetJoinId(expr->id()); |
4533 set_current_block(function_return()); | 4529 set_current_block(function_return()); |
4534 } else { | 4530 } else { |
4535 set_current_block(NULL); | 4531 set_current_block(NULL); |
4536 } | 4532 } |
4537 | 4533 |
(...skipping 2036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6574 } | 6570 } |
6575 } | 6571 } |
6576 | 6572 |
6577 #ifdef DEBUG | 6573 #ifdef DEBUG |
6578 if (graph_ != NULL) graph_->Verify(); | 6574 if (graph_ != NULL) graph_->Verify(); |
6579 if (allocator_ != NULL) allocator_->Verify(); | 6575 if (allocator_ != NULL) allocator_->Verify(); |
6580 #endif | 6576 #endif |
6581 } | 6577 } |
6582 | 6578 |
6583 } } // namespace v8::internal | 6579 } } // namespace v8::internal |
OLD | NEW |