| 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 |