Chromium Code Reviews| 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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 } else if (then_graph->HasExit()) { | 495 } else if (then_graph->HasExit()) { |
| 496 exit_block_ = then_graph->exit_block_; | 496 exit_block_ = then_graph->exit_block_; |
| 497 } else if (else_graph->HasExit()) { | 497 } else if (else_graph->HasExit()) { |
| 498 exit_block_ = else_graph->exit_block_; | 498 exit_block_ = else_graph->exit_block_; |
| 499 } else { | 499 } else { |
| 500 exit_block_ = NULL; | 500 exit_block_ = NULL; |
| 501 } | 501 } |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 void HSubgraph::ResolveContinue(IterationStatement* statement) { | 505 void HSubgraph::ResolveContinue(IterationStatement* statement, |
|
Kevin Millikin (Chromium)
2011/02/21 15:41:07
I have tried to keep these helpers and their use a
| |
| 506 HBasicBlock* continue_block = BundleContinue(statement); | 506 HBasicBlock* continue_block) { |
| 507 if (continue_block != NULL) { | 507 if (continue_block != NULL) { |
| 508 exit_block_ = JoinBlocks(exit_block(), | 508 continue_block->SetJoinId(statement->ContinueId()); |
| 509 continue_block, | |
| 510 statement->ContinueId()); | |
| 511 } | 509 } |
| 510 exit_block_ = | |
| 511 JoinBlocks(exit_block(), continue_block, statement->ContinueId()); | |
| 512 } | 512 } |
| 513 | 513 |
| 514 | 514 |
| 515 HBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) { | |
| 516 return BundleBreakContinue(statement, false, statement->ExitId()); | |
| 517 } | |
| 518 | |
| 519 | |
| 520 HBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) { | |
| 521 return BundleBreakContinue(statement, true, statement->ContinueId()); | |
| 522 } | |
| 523 | |
| 524 | |
| 525 HBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement, | |
| 526 bool is_continue, | |
| 527 int join_id) { | |
| 528 HBasicBlock* result = NULL; | |
| 529 const ZoneList<BreakContinueInfo*>* infos = break_continue_info(); | |
|
Kevin Millikin (Chromium)
2011/02/21 15:41:07
Before, we kept this zone-allocated list of blocks
| |
| 530 for (int i = 0; i < infos->length(); ++i) { | |
| 531 BreakContinueInfo* info = infos->at(i); | |
| 532 if (info->is_continue() == is_continue && | |
| 533 info->target() == statement && | |
| 534 !info->IsResolved()) { | |
| 535 if (result == NULL) { | |
| 536 result = graph_->CreateBasicBlock(); | |
| 537 } | |
| 538 info->block()->Goto(result); | |
| 539 info->Resolve(); | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 if (result != NULL) result->SetJoinId(join_id); | |
| 544 | |
| 545 return result; | |
| 546 } | |
| 547 | |
| 548 | |
| 549 HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { | 515 HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { |
| 550 if (a == NULL) return b; | 516 if (a == NULL) return b; |
| 551 if (b == NULL) return a; | 517 if (b == NULL) return a; |
| 552 HBasicBlock* target = graph_->CreateBasicBlock(); | 518 HBasicBlock* target = graph_->CreateBasicBlock(); |
| 553 a->Goto(target); | 519 a->Goto(target); |
| 554 b->Goto(target); | 520 b->Goto(target); |
| 555 target->SetJoinId(id); | 521 target->SetJoinId(id); |
| 556 return target; | 522 return target; |
| 557 } | 523 } |
| 558 | 524 |
| 559 | 525 |
| 560 void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) { | 526 void HSubgraph::AppendEndless(HSubgraph* body, |
|
Kevin Millikin (Chromium)
2011/02/21 15:41:07
Everywhere we used to call ResolveContinue or Bund
| |
| 527 IterationStatement* statement, | |
| 528 HBasicBlock* break_block) { | |
| 561 ConnectExitTo(body->entry_block()); | 529 ConnectExitTo(body->entry_block()); |
| 562 body->ResolveContinue(statement); | |
|
Kevin Millikin (Chromium)
2011/02/21 15:41:07
This call was actually unnecessary, because all th
| |
| 563 body->ConnectExitTo(body->entry_block(), true); | 530 body->ConnectExitTo(body->entry_block(), true); |
| 564 exit_block_ = body->BundleBreak(statement); | 531 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
| 532 exit_block_ = break_block; | |
| 565 body->entry_block()->PostProcessLoopHeader(statement); | 533 body->entry_block()->PostProcessLoopHeader(statement); |
| 566 } | 534 } |
| 567 | 535 |
| 568 | 536 |
| 569 void HSubgraph::AppendDoWhile(HSubgraph* body, | 537 void HSubgraph::AppendDoWhile(HSubgraph* body, |
| 570 IterationStatement* statement, | 538 IterationStatement* statement, |
| 571 HSubgraph* go_back, | 539 HSubgraph* go_back, |
| 572 HSubgraph* exit) { | 540 HSubgraph* exit, |
| 541 HBasicBlock* break_block) { | |
| 573 ConnectExitTo(body->entry_block()); | 542 ConnectExitTo(body->entry_block()); |
| 574 go_back->ConnectExitTo(body->entry_block(), true); | 543 go_back->ConnectExitTo(body->entry_block(), true); |
| 575 | 544 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
| 576 HBasicBlock* break_block = body->BundleBreak(statement); | |
| 577 exit_block_ = | 545 exit_block_ = |
| 578 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); | 546 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
| 579 body->entry_block()->PostProcessLoopHeader(statement); | 547 body->entry_block()->PostProcessLoopHeader(statement); |
| 580 } | 548 } |
| 581 | 549 |
| 582 | 550 |
| 583 void HSubgraph::AppendWhile(HSubgraph* condition, | 551 void HSubgraph::AppendWhile(HSubgraph* condition, |
| 584 HSubgraph* body, | 552 HSubgraph* body, |
| 585 IterationStatement* statement, | 553 IterationStatement* statement, |
| 586 HSubgraph* continue_subgraph, | 554 HSubgraph* continue_subgraph, |
| 587 HSubgraph* exit) { | 555 HSubgraph* exit, |
| 556 HBasicBlock* break_block) { | |
| 588 ConnectExitTo(condition->entry_block()); | 557 ConnectExitTo(condition->entry_block()); |
| 589 | 558 |
| 590 HBasicBlock* break_block = body->BundleBreak(statement); | 559 if (break_block != NULL) break_block->SetJoinId(statement->ExitId()); |
| 591 exit_block_ = | 560 exit_block_ = |
| 592 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); | 561 JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); |
| 593 | 562 |
| 594 if (continue_subgraph != NULL) { | 563 if (continue_subgraph != NULL) { |
| 595 body->ConnectExitTo(continue_subgraph->entry_block(), true); | 564 body->ConnectExitTo(continue_subgraph->entry_block(), true); |
| 596 continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); | 565 continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); |
| 597 exit_block_ = JoinBlocks(exit_block_, | 566 exit_block_ = JoinBlocks(exit_block_, |
| 598 continue_subgraph->exit_block(), | 567 continue_subgraph->exit_block(), |
| 599 statement->ExitId()); | 568 statement->ExitId()); |
| 600 } else { | 569 } else { |
| 601 body->ConnectExitTo(condition->entry_block(), true); | 570 body->ConnectExitTo(condition->entry_block(), true); |
| 602 } | 571 } |
| 603 condition->entry_block()->PostProcessLoopHeader(statement); | 572 condition->entry_block()->PostProcessLoopHeader(statement); |
| 604 } | 573 } |
| 605 | 574 |
| 606 | 575 |
| 607 void HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) { | 576 void HSubgraph::Append(HSubgraph* next, |
| 577 BreakableStatement* stmt, | |
| 578 HBasicBlock* break_block) { | |
| 608 exit_block_->Goto(next->entry_block()); | 579 exit_block_->Goto(next->entry_block()); |
| 609 exit_block_ = next->exit_block_; | 580 exit_block_ = next->exit_block_; |
| 610 | 581 |
| 611 if (stmt != NULL) { | 582 if (stmt != NULL) { |
| 612 next->entry_block()->SetJoinId(stmt->EntryId()); | 583 next->entry_block()->SetJoinId(stmt->EntryId()); |
| 613 HBasicBlock* break_block = next->BundleBreak(stmt); | 584 if (break_block != NULL) break_block->SetJoinId(stmt->EntryId()); |
| 614 exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); | 585 exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); |
| 615 } | 586 } |
| 616 } | 587 } |
| 617 | 588 |
| 618 | 589 |
| 619 void HSubgraph::FinishExit(HControlInstruction* instruction) { | 590 void HSubgraph::FinishExit(HControlInstruction* instruction) { |
| 620 ASSERT(HasExit()); | 591 ASSERT(HasExit()); |
| 621 exit_block_->Finish(instruction); | 592 exit_block_->Finish(instruction); |
| 622 exit_block_->ClearEnvironment(); | 593 exit_block_->ClearEnvironment(); |
| 623 exit_block_ = NULL; | 594 exit_block_ = NULL; |
| 624 } | 595 } |
| 625 | 596 |
| 626 | 597 |
| 627 void HSubgraph::FinishBreakContinue(BreakableStatement* target, | |
| 628 bool is_continue) { | |
| 629 ASSERT(!exit_block_->IsFinished()); | |
| 630 BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_, | |
| 631 is_continue); | |
| 632 break_continue_info_.Add(info); | |
| 633 exit_block_ = NULL; | |
| 634 } | |
| 635 | |
| 636 | |
| 637 HGraph::HGraph(CompilationInfo* info) | 598 HGraph::HGraph(CompilationInfo* info) |
| 638 : HSubgraph(this), | 599 : HSubgraph(this), |
| 639 next_block_id_(0), | 600 next_block_id_(0), |
| 640 info_(info), | 601 info_(info), |
| 641 blocks_(8), | 602 blocks_(8), |
| 642 values_(16), | 603 values_(16), |
| 643 phi_list_(NULL) { | 604 phi_list_(NULL) { |
| 644 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); | 605 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); |
| 645 start_environment_->set_ast_id(info->function()->id()); | 606 start_environment_->set_ast_id(info->function()->id()); |
| 646 } | 607 } |
| (...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2106 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { | 2067 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { |
| 2107 public: | 2068 public: |
| 2108 SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph) | 2069 SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph) |
| 2109 : builder_(builder) { | 2070 : builder_(builder) { |
| 2110 old_subgraph_ = builder_->current_subgraph_; | 2071 old_subgraph_ = builder_->current_subgraph_; |
| 2111 subgraph_ = new_subgraph; | 2072 subgraph_ = new_subgraph; |
| 2112 builder_->current_subgraph_ = subgraph_; | 2073 builder_->current_subgraph_ = subgraph_; |
| 2113 } | 2074 } |
| 2114 | 2075 |
| 2115 ~SubgraphScope() { | 2076 ~SubgraphScope() { |
| 2116 old_subgraph_->AddBreakContinueInfo(subgraph_); | |
|
Kevin Millikin (Chromium)
2011/02/21 15:41:07
Here we copied all the unhandled breaks and contin
| |
| 2117 builder_->current_subgraph_ = old_subgraph_; | 2077 builder_->current_subgraph_ = old_subgraph_; |
| 2118 } | 2078 } |
| 2119 | 2079 |
| 2120 HSubgraph* subgraph() const { return subgraph_; } | 2080 HSubgraph* subgraph() const { return subgraph_; } |
| 2121 | 2081 |
| 2122 private: | 2082 private: |
| 2123 HGraphBuilder* builder_; | 2083 HGraphBuilder* builder_; |
| 2124 HSubgraph* old_subgraph_; | 2084 HSubgraph* old_subgraph_; |
| 2125 HSubgraph* subgraph_; | 2085 HSubgraph* subgraph_; |
| 2126 }; | 2086 }; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2180 Scope* scope = info->scope(); | 2140 Scope* scope = info->scope(); |
| 2181 SetupScope(scope); | 2141 SetupScope(scope); |
| 2182 VisitDeclarations(scope->declarations()); | 2142 VisitDeclarations(scope->declarations()); |
| 2183 | 2143 |
| 2184 AddInstruction(new HStackCheck()); | 2144 AddInstruction(new HStackCheck()); |
| 2185 | 2145 |
| 2186 ZoneList<Statement*>* stmts = info->function()->body(); | 2146 ZoneList<Statement*>* stmts = info->function()->body(); |
| 2187 HSubgraph* body = CreateGotoSubgraph(environment()); | 2147 HSubgraph* body = CreateGotoSubgraph(environment()); |
| 2188 AddToSubgraph(body, stmts); | 2148 AddToSubgraph(body, stmts); |
| 2189 if (HasStackOverflow()) return NULL; | 2149 if (HasStackOverflow()) return NULL; |
| 2190 current_subgraph_->Append(body, NULL); | 2150 current_subgraph_->Append(body, NULL, NULL); |
| 2191 body->entry_block()->SetJoinId(info->function()->id()); | 2151 body->entry_block()->SetJoinId(info->function()->id()); |
| 2192 | 2152 |
| 2193 if (graph_->HasExit()) { | 2153 if (graph_->HasExit()) { |
| 2194 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); | 2154 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); |
| 2195 } | 2155 } |
| 2196 } | 2156 } |
| 2197 | 2157 |
| 2198 graph_->OrderBlocks(); | 2158 graph_->OrderBlocks(); |
| 2199 graph_->AssignDominators(); | 2159 graph_->AssignDominators(); |
| 2200 graph_->EliminateRedundantPhis(); | 2160 graph_->EliminateRedundantPhis(); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2382 block->SetInitialEnvironment(new_env); | 2342 block->SetInitialEnvironment(new_env); |
| 2383 subgraph->Initialize(block); | 2343 subgraph->Initialize(block); |
| 2384 subgraph->entry_block()->AttachLoopInformation(); | 2344 subgraph->entry_block()->AttachLoopInformation(); |
| 2385 return subgraph; | 2345 return subgraph; |
| 2386 } | 2346 } |
| 2387 | 2347 |
| 2388 | 2348 |
| 2389 void HGraphBuilder::VisitBlock(Block* stmt) { | 2349 void HGraphBuilder::VisitBlock(Block* stmt) { |
| 2390 if (stmt->labels() != NULL) { | 2350 if (stmt->labels() != NULL) { |
| 2391 HSubgraph* block_graph = CreateGotoSubgraph(environment()); | 2351 HSubgraph* block_graph = CreateGotoSubgraph(environment()); |
| 2392 ADD_TO_SUBGRAPH(block_graph, stmt->statements()); | 2352 BreakAndContinueInfo break_info(stmt); |
| 2393 current_subgraph_->Append(block_graph, stmt); | 2353 { BreakStackEntry push(&break_info, this); |
| 2354 ADD_TO_SUBGRAPH(block_graph, stmt->statements()); | |
| 2355 } | |
| 2356 subgraph()->Append(block_graph, stmt, break_info.break_block()); | |
| 2394 } else { | 2357 } else { |
| 2395 VisitStatements(stmt->statements()); | 2358 VisitStatements(stmt->statements()); |
| 2396 } | 2359 } |
| 2397 } | 2360 } |
| 2398 | 2361 |
| 2399 | 2362 |
| 2400 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { | 2363 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 2401 VisitForEffect(stmt->expression()); | 2364 VisitForEffect(stmt->expression()); |
| 2402 } | 2365 } |
| 2403 | 2366 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2424 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); | 2387 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); |
| 2425 | 2388 |
| 2426 else_graph->entry_block()->SetJoinId(stmt->ElseId()); | 2389 else_graph->entry_block()->SetJoinId(stmt->ElseId()); |
| 2427 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); | 2390 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); |
| 2428 | 2391 |
| 2429 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); | 2392 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); |
| 2430 } | 2393 } |
| 2431 } | 2394 } |
| 2432 | 2395 |
| 2433 | 2396 |
| 2397 HBasicBlock* HGraphBuilder::BreakStackEntry::Get(BreakableStatement* stmt, | |
| 2398 BreakType type) { | |
| 2399 BreakStackEntry* current = this; | |
| 2400 while (current != NULL && current->info()->target() != stmt) { | |
| 2401 current = current->next(); | |
| 2402 } | |
| 2403 ASSERT(current != NULL); // Always found (unless stack is malformed). | |
| 2404 HBasicBlock* block = NULL; | |
| 2405 switch (type) { | |
| 2406 case BREAK: | |
| 2407 block = current->info()->break_block(); | |
| 2408 if (block == NULL) { | |
| 2409 block = current->owner()->graph()->CreateBasicBlock(); | |
| 2410 current->info()->set_break_block(block); | |
| 2411 } | |
| 2412 break; | |
| 2413 | |
| 2414 case CONTINUE: | |
| 2415 block = current->info()->continue_block(); | |
| 2416 if (block == NULL) { | |
| 2417 block = current->owner()->graph()->CreateBasicBlock(); | |
| 2418 current->info()->set_continue_block(block); | |
| 2419 } | |
| 2420 break; | |
| 2421 } | |
| 2422 | |
| 2423 return block; | |
| 2424 } | |
| 2425 | |
| 2426 | |
| 2434 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 2427 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
| 2435 current_subgraph_->FinishBreakContinue(stmt->target(), true); | 2428 HBasicBlock* continue_block = break_stack()->Get(stmt->target(), CONTINUE); |
| 2429 subgraph()->exit_block()->Goto(continue_block); | |
| 2430 subgraph()->set_exit_block(NULL); | |
| 2436 } | 2431 } |
| 2437 | 2432 |
| 2438 | 2433 |
| 2439 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 2434 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
| 2440 current_subgraph_->FinishBreakContinue(stmt->target(), false); | 2435 HBasicBlock* break_block = break_stack()->Get(stmt->target(), BREAK); |
| 2436 subgraph()->exit_block()->Goto(break_block); | |
| 2437 subgraph()->set_exit_block(NULL); | |
| 2441 } | 2438 } |
| 2442 | 2439 |
| 2443 | 2440 |
| 2444 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2441 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 2445 AstContext* context = call_context(); | 2442 AstContext* context = call_context(); |
| 2446 if (context == NULL) { | 2443 if (context == NULL) { |
| 2447 // Not an inlined return, so an actual one. | 2444 // Not an inlined return, so an actual one. |
| 2448 VISIT_FOR_VALUE(stmt->expression()); | 2445 VISIT_FOR_VALUE(stmt->expression()); |
| 2449 HValue* result = environment()->Pop(); | 2446 HValue* result = environment()->Pop(); |
| 2450 subgraph()->FinishExit(new HReturn(result)); | 2447 subgraph()->FinishExit(new HReturn(result)); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2613 } | 2610 } |
| 2614 | 2611 |
| 2615 // Check for fall-through from previous statement block. | 2612 // Check for fall-through from previous statement block. |
| 2616 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2613 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { |
| 2617 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); | 2614 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); |
| 2618 previous_subgraph->exit_block()-> | 2615 previous_subgraph->exit_block()-> |
| 2619 Finish(new HGoto(subgraph->entry_block())); | 2616 Finish(new HGoto(subgraph->entry_block())); |
| 2620 } | 2617 } |
| 2621 | 2618 |
| 2622 if (subgraph != NULL) { | 2619 if (subgraph != NULL) { |
| 2623 ADD_TO_SUBGRAPH(subgraph, clause->statements()); | 2620 BreakAndContinueInfo break_info(stmt); |
| 2624 HBasicBlock* break_block = subgraph->BundleBreak(stmt); | 2621 { BreakStackEntry push(&break_info, this); |
| 2625 if (break_block != NULL) { | 2622 ADD_TO_SUBGRAPH(subgraph, clause->statements()); |
| 2626 break_block->Finish(new HGoto(single_exit_block)); | 2623 } |
| 2624 if (break_info.break_block() != NULL) { | |
| 2625 break_info.break_block()->SetJoinId(stmt->ExitId()); | |
| 2626 break_info.break_block()->Finish(new HGoto(single_exit_block)); | |
| 2627 } | 2627 } |
| 2628 } | 2628 } |
| 2629 | 2629 |
| 2630 previous_subgraph = subgraph; | 2630 previous_subgraph = subgraph; |
| 2631 } | 2631 } |
| 2632 | 2632 |
| 2633 // If the last statement block has a fall-through, connect it to the | 2633 // If the last statement block has a fall-through, connect it to the |
| 2634 // single exit block. | 2634 // single exit block. |
| 2635 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2635 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { |
| 2636 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); | 2636 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2683 loop_predecessor->SetJoinId(statement->EntryId()); | 2683 loop_predecessor->SetJoinId(statement->EntryId()); |
| 2684 set_exit_block(loop_predecessor); | 2684 set_exit_block(loop_predecessor); |
| 2685 } | 2685 } |
| 2686 | 2686 |
| 2687 | 2687 |
| 2688 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2688 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 2689 ASSERT(subgraph()->HasExit()); | 2689 ASSERT(subgraph()->HasExit()); |
| 2690 subgraph()->PreProcessOsrEntry(stmt); | 2690 subgraph()->PreProcessOsrEntry(stmt); |
| 2691 | 2691 |
| 2692 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); | 2692 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); |
| 2693 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2693 BreakAndContinueInfo break_info(stmt); |
| 2694 body_graph->ResolveContinue(stmt); | 2694 { BreakStackEntry push(&break_info, this); |
| 2695 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
| 2696 } | |
| 2697 body_graph->ResolveContinue(stmt, break_info.continue_block()); | |
| 2695 | 2698 |
| 2696 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { | 2699 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { |
| 2697 current_subgraph_->AppendEndless(body_graph, stmt); | 2700 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
| 2698 } else { | 2701 } else { |
| 2699 HSubgraph* go_back = CreateEmptySubgraph(); | 2702 HSubgraph* go_back = CreateEmptySubgraph(); |
| 2700 HSubgraph* exit = CreateEmptySubgraph(); | 2703 HSubgraph* exit = CreateEmptySubgraph(); |
| 2701 { | 2704 { |
| 2702 SubgraphScope scope(this, body_graph); | 2705 SubgraphScope scope(this, body_graph); |
| 2703 VISIT_FOR_CONTROL(stmt->cond(), | 2706 VISIT_FOR_CONTROL(stmt->cond(), |
| 2704 go_back->entry_block(), | 2707 go_back->entry_block(), |
| 2705 exit->entry_block()); | 2708 exit->entry_block()); |
| 2706 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); | 2709 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); |
| 2707 exit->entry_block()->SetJoinId(stmt->ExitId()); | 2710 exit->entry_block()->SetJoinId(stmt->ExitId()); |
| 2708 } | 2711 } |
| 2709 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); | 2712 subgraph()->AppendDoWhile(body_graph, stmt, go_back, exit, |
| 2713 break_info.break_block()); | |
| 2710 } | 2714 } |
| 2711 } | 2715 } |
| 2712 | 2716 |
| 2713 | 2717 |
| 2714 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { | 2718 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { |
| 2715 return FLAG_use_peeling; | 2719 return FLAG_use_peeling; |
| 2716 } | 2720 } |
| 2717 | 2721 |
| 2718 | 2722 |
| 2719 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2723 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 2720 ASSERT(subgraph()->HasExit()); | 2724 ASSERT(subgraph()->HasExit()); |
| 2721 subgraph()->PreProcessOsrEntry(stmt); | 2725 subgraph()->PreProcessOsrEntry(stmt); |
| 2722 | 2726 |
| 2723 HSubgraph* cond_graph = NULL; | 2727 HSubgraph* cond_graph = NULL; |
| 2724 HSubgraph* body_graph = NULL; | 2728 HSubgraph* body_graph = NULL; |
| 2725 HSubgraph* exit_graph = NULL; | 2729 HSubgraph* exit_graph = NULL; |
| 2726 | 2730 |
| 2727 // If the condition is constant true, do not generate a condition subgraph. | 2731 // If the condition is constant true, do not generate a condition subgraph. |
| 2728 if (stmt->cond()->ToBooleanIsTrue()) { | 2732 if (stmt->cond()->ToBooleanIsTrue()) { |
| 2729 body_graph = CreateLoopHeaderSubgraph(environment()); | 2733 body_graph = CreateLoopHeaderSubgraph(environment()); |
| 2730 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
| 2731 } else { | 2734 } else { |
| 2732 cond_graph = CreateLoopHeaderSubgraph(environment()); | 2735 cond_graph = CreateLoopHeaderSubgraph(environment()); |
| 2733 body_graph = CreateEmptySubgraph(); | 2736 body_graph = CreateEmptySubgraph(); |
| 2734 exit_graph = CreateEmptySubgraph(); | 2737 exit_graph = CreateEmptySubgraph(); |
| 2735 { | 2738 { |
| 2736 SubgraphScope scope(this, cond_graph); | 2739 SubgraphScope scope(this, cond_graph); |
| 2737 VISIT_FOR_CONTROL(stmt->cond(), | 2740 VISIT_FOR_CONTROL(stmt->cond(), |
| 2738 body_graph->entry_block(), | 2741 body_graph->entry_block(), |
| 2739 exit_graph->entry_block()); | 2742 exit_graph->entry_block()); |
| 2740 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 2743 body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
| 2741 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 2744 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
| 2742 } | 2745 } |
| 2746 } | |
| 2747 | |
| 2748 BreakAndContinueInfo break_info(stmt); | |
| 2749 { BreakStackEntry push(&break_info, this); | |
| 2743 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2750 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
| 2744 } | 2751 } |
| 2745 | 2752 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
| 2746 body_graph->ResolveContinue(stmt); | |
| 2747 | 2753 |
| 2748 if (cond_graph != NULL) { | 2754 if (cond_graph != NULL) { |
| 2749 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); | 2755 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
| 2756 break_info.break_block()); | |
| 2750 } else { | 2757 } else { |
| 2751 // TODO(fschneider): Implement peeling for endless loops as well. | 2758 // TODO(fschneider): Implement peeling for endless loops as well. |
| 2752 current_subgraph_->AppendEndless(body_graph, stmt); | 2759 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
| 2753 } | 2760 } |
| 2754 } | 2761 } |
| 2755 | 2762 |
| 2756 | 2763 |
| 2757 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, | 2764 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, |
| 2758 HSubgraph* cond_graph, | 2765 HSubgraph* cond_graph, |
| 2759 HSubgraph* body_graph, | 2766 HSubgraph* body_graph, |
| 2760 HSubgraph* exit_graph) { | 2767 HSubgraph* exit_graph, |
| 2768 HBasicBlock* break_block) { | |
| 2761 HSubgraph* loop = NULL; | 2769 HSubgraph* loop = NULL; |
| 2762 if (body_graph->HasExit() && stmt != peeled_statement_ && | 2770 if (body_graph->HasExit() && stmt != peeled_statement_ && |
| 2763 ShouldPeel(cond_graph, body_graph)) { | 2771 ShouldPeel(cond_graph, body_graph)) { |
| 2764 // Save the last peeled iteration statement to prevent infinite recursion. | 2772 // Save the last peeled iteration statement to prevent infinite recursion. |
| 2765 IterationStatement* outer_peeled_statement = peeled_statement_; | 2773 IterationStatement* outer_peeled_statement = peeled_statement_; |
| 2766 peeled_statement_ = stmt; | 2774 peeled_statement_ = stmt; |
| 2767 loop = CreateGotoSubgraph(body_graph->environment()); | 2775 loop = CreateGotoSubgraph(body_graph->environment()); |
| 2768 ADD_TO_SUBGRAPH(loop, stmt); | 2776 ADD_TO_SUBGRAPH(loop, stmt); |
| 2769 peeled_statement_ = outer_peeled_statement; | 2777 peeled_statement_ = outer_peeled_statement; |
| 2770 } | 2778 } |
| 2771 current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop, | 2779 subgraph()->AppendWhile(cond_graph, body_graph, stmt, loop, exit_graph, |
| 2772 exit_graph); | 2780 break_block); |
| 2773 } | 2781 } |
| 2774 | 2782 |
| 2775 | 2783 |
| 2776 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 2784 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 2777 // Only visit the init statement in the peeled part of the loop. | 2785 // Only visit the init statement in the peeled part of the loop. |
| 2778 if (stmt->init() != NULL && peeled_statement_ != stmt) { | 2786 if (stmt->init() != NULL && peeled_statement_ != stmt) { |
| 2779 Visit(stmt->init()); | 2787 Visit(stmt->init()); |
| 2780 CHECK_BAILOUT; | 2788 CHECK_BAILOUT; |
| 2781 } | 2789 } |
| 2782 ASSERT(subgraph()->HasExit()); | 2790 ASSERT(subgraph()->HasExit()); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2793 SubgraphScope scope(this, cond_graph); | 2801 SubgraphScope scope(this, cond_graph); |
| 2794 VISIT_FOR_CONTROL(stmt->cond(), | 2802 VISIT_FOR_CONTROL(stmt->cond(), |
| 2795 body_graph->entry_block(), | 2803 body_graph->entry_block(), |
| 2796 exit_graph->entry_block()); | 2804 exit_graph->entry_block()); |
| 2797 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 2805 body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
| 2798 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 2806 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
| 2799 } | 2807 } |
| 2800 } else { | 2808 } else { |
| 2801 body_graph = CreateLoopHeaderSubgraph(environment()); | 2809 body_graph = CreateLoopHeaderSubgraph(environment()); |
| 2802 } | 2810 } |
| 2803 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2811 BreakAndContinueInfo break_info(stmt); |
| 2812 { BreakStackEntry push(&break_info, this); | |
| 2813 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
| 2814 } | |
| 2804 | 2815 |
| 2805 HSubgraph* next_graph = NULL; | 2816 HSubgraph* next_graph = NULL; |
| 2806 body_graph->ResolveContinue(stmt); | 2817 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
| 2807 | 2818 |
| 2808 if (stmt->next() != NULL && body_graph->HasExit()) { | 2819 if (stmt->next() != NULL && body_graph->HasExit()) { |
| 2809 next_graph = CreateGotoSubgraph(body_graph->environment()); | 2820 next_graph = CreateGotoSubgraph(body_graph->environment()); |
| 2810 ADD_TO_SUBGRAPH(next_graph, stmt->next()); | 2821 ADD_TO_SUBGRAPH(next_graph, stmt->next()); |
| 2811 body_graph->Append(next_graph, NULL); | 2822 body_graph->Append(next_graph, NULL, NULL); |
| 2812 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); | 2823 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); |
| 2813 } | 2824 } |
| 2814 | 2825 |
| 2815 if (cond_graph != NULL) { | 2826 if (cond_graph != NULL) { |
| 2816 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); | 2827 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
| 2828 break_info.break_block()); | |
| 2817 } else { | 2829 } else { |
| 2818 current_subgraph_->AppendEndless(body_graph, stmt); | 2830 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
| 2819 } | 2831 } |
| 2820 } | 2832 } |
| 2821 | 2833 |
| 2822 | 2834 |
| 2823 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 2835 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 2824 BAILOUT("ForInStatement"); | 2836 BAILOUT("ForInStatement"); |
| 2825 } | 2837 } |
| 2826 | 2838 |
| 2827 | 2839 |
| 2828 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 2840 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| (...skipping 3212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6041 } | 6053 } |
| 6042 } | 6054 } |
| 6043 | 6055 |
| 6044 #ifdef DEBUG | 6056 #ifdef DEBUG |
| 6045 if (graph_ != NULL) graph_->Verify(); | 6057 if (graph_ != NULL) graph_->Verify(); |
| 6046 if (allocator_ != NULL) allocator_->Verify(); | 6058 if (allocator_ != NULL) allocator_->Verify(); |
| 6047 #endif | 6059 #endif |
| 6048 } | 6060 } |
| 6049 | 6061 |
| 6050 } } // namespace v8::internal | 6062 } } // namespace v8::internal |
| OLD | NEW |