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

Side by Side Diff: src/hydrogen.cc

Issue 7216009: Change the handling of stack check on backward branches (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Changed stack check elimination to remove the stack check instruction Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698