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, |
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(); | |
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, |
| 527 IterationStatement* statement, |
| 528 HBasicBlock* break_block) { |
561 ConnectExitTo(body->entry_block()); | 529 ConnectExitTo(body->entry_block()); |
562 body->ResolveContinue(statement); | |
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_); | |
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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2188 Scope* scope = info->scope(); | 2148 Scope* scope = info->scope(); |
2189 SetupScope(scope); | 2149 SetupScope(scope); |
2190 VisitDeclarations(scope->declarations()); | 2150 VisitDeclarations(scope->declarations()); |
2191 | 2151 |
2192 AddInstruction(new HStackCheck()); | 2152 AddInstruction(new HStackCheck()); |
2193 | 2153 |
2194 ZoneList<Statement*>* stmts = info->function()->body(); | 2154 ZoneList<Statement*>* stmts = info->function()->body(); |
2195 HSubgraph* body = CreateGotoSubgraph(environment()); | 2155 HSubgraph* body = CreateGotoSubgraph(environment()); |
2196 AddToSubgraph(body, stmts); | 2156 AddToSubgraph(body, stmts); |
2197 if (HasStackOverflow()) return NULL; | 2157 if (HasStackOverflow()) return NULL; |
2198 current_subgraph_->Append(body, NULL); | 2158 current_subgraph_->Append(body, NULL, NULL); |
2199 body->entry_block()->SetJoinId(info->function()->id()); | 2159 body->entry_block()->SetJoinId(info->function()->id()); |
2200 | 2160 |
2201 if (graph_->HasExit()) { | 2161 if (graph_->HasExit()) { |
2202 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); | 2162 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); |
2203 } | 2163 } |
2204 } | 2164 } |
2205 | 2165 |
2206 graph_->OrderBlocks(); | 2166 graph_->OrderBlocks(); |
2207 graph_->AssignDominators(); | 2167 graph_->AssignDominators(); |
2208 graph_->EliminateRedundantPhis(); | 2168 graph_->EliminateRedundantPhis(); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2390 block->SetInitialEnvironment(new_env); | 2350 block->SetInitialEnvironment(new_env); |
2391 subgraph->Initialize(block); | 2351 subgraph->Initialize(block); |
2392 subgraph->entry_block()->AttachLoopInformation(); | 2352 subgraph->entry_block()->AttachLoopInformation(); |
2393 return subgraph; | 2353 return subgraph; |
2394 } | 2354 } |
2395 | 2355 |
2396 | 2356 |
2397 void HGraphBuilder::VisitBlock(Block* stmt) { | 2357 void HGraphBuilder::VisitBlock(Block* stmt) { |
2398 if (stmt->labels() != NULL) { | 2358 if (stmt->labels() != NULL) { |
2399 HSubgraph* block_graph = CreateGotoSubgraph(environment()); | 2359 HSubgraph* block_graph = CreateGotoSubgraph(environment()); |
2400 ADD_TO_SUBGRAPH(block_graph, stmt->statements()); | 2360 BreakAndContinueInfo break_info(stmt); |
2401 current_subgraph_->Append(block_graph, stmt); | 2361 { BreakAndContinueScope push(&break_info, this); |
| 2362 ADD_TO_SUBGRAPH(block_graph, stmt->statements()); |
| 2363 } |
| 2364 subgraph()->Append(block_graph, stmt, break_info.break_block()); |
2402 } else { | 2365 } else { |
2403 VisitStatements(stmt->statements()); | 2366 VisitStatements(stmt->statements()); |
2404 } | 2367 } |
2405 } | 2368 } |
2406 | 2369 |
2407 | 2370 |
2408 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { | 2371 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { |
2409 VisitForEffect(stmt->expression()); | 2372 VisitForEffect(stmt->expression()); |
2410 } | 2373 } |
2411 | 2374 |
(...skipping 20 matching lines...) Expand all Loading... |
2432 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); | 2395 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); |
2433 | 2396 |
2434 else_graph->entry_block()->SetJoinId(stmt->ElseId()); | 2397 else_graph->entry_block()->SetJoinId(stmt->ElseId()); |
2435 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); | 2398 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); |
2436 | 2399 |
2437 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); | 2400 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); |
2438 } | 2401 } |
2439 } | 2402 } |
2440 | 2403 |
2441 | 2404 |
| 2405 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( |
| 2406 BreakableStatement* stmt, |
| 2407 BreakType type) { |
| 2408 BreakAndContinueScope* current = this; |
| 2409 while (current != NULL && current->info()->target() != stmt) { |
| 2410 current = current->next(); |
| 2411 } |
| 2412 ASSERT(current != NULL); // Always found (unless stack is malformed). |
| 2413 HBasicBlock* block = NULL; |
| 2414 switch (type) { |
| 2415 case BREAK: |
| 2416 block = current->info()->break_block(); |
| 2417 if (block == NULL) { |
| 2418 block = current->owner()->graph()->CreateBasicBlock(); |
| 2419 current->info()->set_break_block(block); |
| 2420 } |
| 2421 break; |
| 2422 |
| 2423 case CONTINUE: |
| 2424 block = current->info()->continue_block(); |
| 2425 if (block == NULL) { |
| 2426 block = current->owner()->graph()->CreateBasicBlock(); |
| 2427 current->info()->set_continue_block(block); |
| 2428 } |
| 2429 break; |
| 2430 } |
| 2431 |
| 2432 return block; |
| 2433 } |
| 2434 |
| 2435 |
2442 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 2436 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
2443 current_subgraph_->FinishBreakContinue(stmt->target(), true); | 2437 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); |
| 2438 subgraph()->exit_block()->Goto(continue_block); |
| 2439 subgraph()->set_exit_block(NULL); |
2444 } | 2440 } |
2445 | 2441 |
2446 | 2442 |
2447 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 2443 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
2448 current_subgraph_->FinishBreakContinue(stmt->target(), false); | 2444 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); |
| 2445 subgraph()->exit_block()->Goto(break_block); |
| 2446 subgraph()->set_exit_block(NULL); |
2449 } | 2447 } |
2450 | 2448 |
2451 | 2449 |
2452 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2450 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
2453 AstContext* context = call_context(); | 2451 AstContext* context = call_context(); |
2454 if (context == NULL) { | 2452 if (context == NULL) { |
2455 // Not an inlined return, so an actual one. | 2453 // Not an inlined return, so an actual one. |
2456 VISIT_FOR_VALUE(stmt->expression()); | 2454 VISIT_FOR_VALUE(stmt->expression()); |
2457 HValue* result = environment()->Pop(); | 2455 HValue* result = environment()->Pop(); |
2458 subgraph()->FinishExit(new HReturn(result)); | 2456 subgraph()->FinishExit(new HReturn(result)); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2621 } | 2619 } |
2622 | 2620 |
2623 // Check for fall-through from previous statement block. | 2621 // Check for fall-through from previous statement block. |
2624 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2622 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { |
2625 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); | 2623 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); |
2626 previous_subgraph->exit_block()-> | 2624 previous_subgraph->exit_block()-> |
2627 Finish(new HGoto(subgraph->entry_block())); | 2625 Finish(new HGoto(subgraph->entry_block())); |
2628 } | 2626 } |
2629 | 2627 |
2630 if (subgraph != NULL) { | 2628 if (subgraph != NULL) { |
2631 ADD_TO_SUBGRAPH(subgraph, clause->statements()); | 2629 BreakAndContinueInfo break_info(stmt); |
2632 HBasicBlock* break_block = subgraph->BundleBreak(stmt); | 2630 { BreakAndContinueScope push(&break_info, this); |
2633 if (break_block != NULL) { | 2631 ADD_TO_SUBGRAPH(subgraph, clause->statements()); |
2634 break_block->Finish(new HGoto(single_exit_block)); | 2632 } |
| 2633 if (break_info.break_block() != NULL) { |
| 2634 break_info.break_block()->SetJoinId(stmt->ExitId()); |
| 2635 break_info.break_block()->Finish(new HGoto(single_exit_block)); |
2635 } | 2636 } |
2636 } | 2637 } |
2637 | 2638 |
2638 previous_subgraph = subgraph; | 2639 previous_subgraph = subgraph; |
2639 } | 2640 } |
2640 | 2641 |
2641 // If the last statement block has a fall-through, connect it to the | 2642 // If the last statement block has a fall-through, connect it to the |
2642 // single exit block. | 2643 // single exit block. |
2643 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { | 2644 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { |
2644 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); | 2645 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2691 loop_predecessor->SetJoinId(statement->EntryId()); | 2692 loop_predecessor->SetJoinId(statement->EntryId()); |
2692 set_exit_block(loop_predecessor); | 2693 set_exit_block(loop_predecessor); |
2693 } | 2694 } |
2694 | 2695 |
2695 | 2696 |
2696 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2697 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
2697 ASSERT(subgraph()->HasExit()); | 2698 ASSERT(subgraph()->HasExit()); |
2698 subgraph()->PreProcessOsrEntry(stmt); | 2699 subgraph()->PreProcessOsrEntry(stmt); |
2699 | 2700 |
2700 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); | 2701 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); |
2701 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2702 BreakAndContinueInfo break_info(stmt); |
2702 body_graph->ResolveContinue(stmt); | 2703 { BreakAndContinueScope push(&break_info, this); |
| 2704 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
| 2705 } |
| 2706 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
2703 | 2707 |
2704 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { | 2708 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { |
2705 current_subgraph_->AppendEndless(body_graph, stmt); | 2709 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
2706 } else { | 2710 } else { |
2707 HSubgraph* go_back = CreateEmptySubgraph(); | 2711 HSubgraph* go_back = CreateEmptySubgraph(); |
2708 HSubgraph* exit = CreateEmptySubgraph(); | 2712 HSubgraph* exit = CreateEmptySubgraph(); |
2709 { | 2713 { |
2710 SubgraphScope scope(this, body_graph); | 2714 SubgraphScope scope(this, body_graph); |
2711 VISIT_FOR_CONTROL(stmt->cond(), | 2715 VISIT_FOR_CONTROL(stmt->cond(), |
2712 go_back->entry_block(), | 2716 go_back->entry_block(), |
2713 exit->entry_block()); | 2717 exit->entry_block()); |
2714 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); | 2718 go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); |
2715 exit->entry_block()->SetJoinId(stmt->ExitId()); | 2719 exit->entry_block()->SetJoinId(stmt->ExitId()); |
2716 } | 2720 } |
2717 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); | 2721 subgraph()->AppendDoWhile(body_graph, stmt, go_back, exit, |
| 2722 break_info.break_block()); |
2718 } | 2723 } |
2719 } | 2724 } |
2720 | 2725 |
2721 | 2726 |
2722 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { | 2727 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { |
2723 return FLAG_use_peeling; | 2728 return FLAG_use_peeling; |
2724 } | 2729 } |
2725 | 2730 |
2726 | 2731 |
2727 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 2732 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
2728 ASSERT(subgraph()->HasExit()); | 2733 ASSERT(subgraph()->HasExit()); |
2729 subgraph()->PreProcessOsrEntry(stmt); | 2734 subgraph()->PreProcessOsrEntry(stmt); |
2730 | 2735 |
2731 HSubgraph* cond_graph = NULL; | 2736 HSubgraph* cond_graph = NULL; |
2732 HSubgraph* body_graph = NULL; | 2737 HSubgraph* body_graph = NULL; |
2733 HSubgraph* exit_graph = NULL; | 2738 HSubgraph* exit_graph = NULL; |
2734 | 2739 |
2735 // If the condition is constant true, do not generate a condition subgraph. | 2740 // If the condition is constant true, do not generate a condition subgraph. |
2736 if (stmt->cond()->ToBooleanIsTrue()) { | 2741 if (stmt->cond()->ToBooleanIsTrue()) { |
2737 body_graph = CreateLoopHeaderSubgraph(environment()); | 2742 body_graph = CreateLoopHeaderSubgraph(environment()); |
2738 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | |
2739 } else { | 2743 } else { |
2740 cond_graph = CreateLoopHeaderSubgraph(environment()); | 2744 cond_graph = CreateLoopHeaderSubgraph(environment()); |
2741 body_graph = CreateEmptySubgraph(); | 2745 body_graph = CreateEmptySubgraph(); |
2742 exit_graph = CreateEmptySubgraph(); | 2746 exit_graph = CreateEmptySubgraph(); |
2743 { | 2747 { |
2744 SubgraphScope scope(this, cond_graph); | 2748 SubgraphScope scope(this, cond_graph); |
2745 VISIT_FOR_CONTROL(stmt->cond(), | 2749 VISIT_FOR_CONTROL(stmt->cond(), |
2746 body_graph->entry_block(), | 2750 body_graph->entry_block(), |
2747 exit_graph->entry_block()); | 2751 exit_graph->entry_block()); |
2748 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 2752 body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
2749 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 2753 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
2750 } | 2754 } |
| 2755 } |
| 2756 |
| 2757 BreakAndContinueInfo break_info(stmt); |
| 2758 { BreakAndContinueScope push(&break_info, this); |
2751 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2759 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
2752 } | 2760 } |
2753 | 2761 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
2754 body_graph->ResolveContinue(stmt); | |
2755 | 2762 |
2756 if (cond_graph != NULL) { | 2763 if (cond_graph != NULL) { |
2757 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); | 2764 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
| 2765 break_info.break_block()); |
2758 } else { | 2766 } else { |
2759 // TODO(fschneider): Implement peeling for endless loops as well. | 2767 // TODO(fschneider): Implement peeling for endless loops as well. |
2760 current_subgraph_->AppendEndless(body_graph, stmt); | 2768 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
2761 } | 2769 } |
2762 } | 2770 } |
2763 | 2771 |
2764 | 2772 |
2765 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, | 2773 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, |
2766 HSubgraph* cond_graph, | 2774 HSubgraph* cond_graph, |
2767 HSubgraph* body_graph, | 2775 HSubgraph* body_graph, |
2768 HSubgraph* exit_graph) { | 2776 HSubgraph* exit_graph, |
| 2777 HBasicBlock* break_block) { |
2769 HSubgraph* loop = NULL; | 2778 HSubgraph* loop = NULL; |
2770 if (body_graph->HasExit() && stmt != peeled_statement_ && | 2779 if (body_graph->HasExit() && stmt != peeled_statement_ && |
2771 ShouldPeel(cond_graph, body_graph)) { | 2780 ShouldPeel(cond_graph, body_graph)) { |
2772 // Save the last peeled iteration statement to prevent infinite recursion. | 2781 // Save the last peeled iteration statement to prevent infinite recursion. |
2773 IterationStatement* outer_peeled_statement = peeled_statement_; | 2782 IterationStatement* outer_peeled_statement = peeled_statement_; |
2774 peeled_statement_ = stmt; | 2783 peeled_statement_ = stmt; |
2775 loop = CreateGotoSubgraph(body_graph->environment()); | 2784 loop = CreateGotoSubgraph(body_graph->environment()); |
2776 ADD_TO_SUBGRAPH(loop, stmt); | 2785 ADD_TO_SUBGRAPH(loop, stmt); |
2777 peeled_statement_ = outer_peeled_statement; | 2786 peeled_statement_ = outer_peeled_statement; |
2778 } | 2787 } |
2779 current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop, | 2788 subgraph()->AppendWhile(cond_graph, body_graph, stmt, loop, exit_graph, |
2780 exit_graph); | 2789 break_block); |
2781 } | 2790 } |
2782 | 2791 |
2783 | 2792 |
2784 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { | 2793 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { |
2785 // Only visit the init statement in the peeled part of the loop. | 2794 // Only visit the init statement in the peeled part of the loop. |
2786 if (stmt->init() != NULL && peeled_statement_ != stmt) { | 2795 if (stmt->init() != NULL && peeled_statement_ != stmt) { |
2787 Visit(stmt->init()); | 2796 Visit(stmt->init()); |
2788 CHECK_BAILOUT; | 2797 CHECK_BAILOUT; |
2789 } | 2798 } |
2790 ASSERT(subgraph()->HasExit()); | 2799 ASSERT(subgraph()->HasExit()); |
(...skipping 10 matching lines...) Expand all Loading... |
2801 SubgraphScope scope(this, cond_graph); | 2810 SubgraphScope scope(this, cond_graph); |
2802 VISIT_FOR_CONTROL(stmt->cond(), | 2811 VISIT_FOR_CONTROL(stmt->cond(), |
2803 body_graph->entry_block(), | 2812 body_graph->entry_block(), |
2804 exit_graph->entry_block()); | 2813 exit_graph->entry_block()); |
2805 body_graph->entry_block()->SetJoinId(stmt->BodyId()); | 2814 body_graph->entry_block()->SetJoinId(stmt->BodyId()); |
2806 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); | 2815 exit_graph->entry_block()->SetJoinId(stmt->ExitId()); |
2807 } | 2816 } |
2808 } else { | 2817 } else { |
2809 body_graph = CreateLoopHeaderSubgraph(environment()); | 2818 body_graph = CreateLoopHeaderSubgraph(environment()); |
2810 } | 2819 } |
2811 ADD_TO_SUBGRAPH(body_graph, stmt->body()); | 2820 BreakAndContinueInfo break_info(stmt); |
| 2821 { BreakAndContinueScope push(&break_info, this); |
| 2822 ADD_TO_SUBGRAPH(body_graph, stmt->body()); |
| 2823 } |
2812 | 2824 |
2813 HSubgraph* next_graph = NULL; | 2825 HSubgraph* next_graph = NULL; |
2814 body_graph->ResolveContinue(stmt); | 2826 body_graph->ResolveContinue(stmt, break_info.continue_block()); |
2815 | 2827 |
2816 if (stmt->next() != NULL && body_graph->HasExit()) { | 2828 if (stmt->next() != NULL && body_graph->HasExit()) { |
2817 next_graph = CreateGotoSubgraph(body_graph->environment()); | 2829 next_graph = CreateGotoSubgraph(body_graph->environment()); |
2818 ADD_TO_SUBGRAPH(next_graph, stmt->next()); | 2830 ADD_TO_SUBGRAPH(next_graph, stmt->next()); |
2819 body_graph->Append(next_graph, NULL); | 2831 body_graph->Append(next_graph, NULL, NULL); |
2820 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); | 2832 next_graph->entry_block()->SetJoinId(stmt->ContinueId()); |
2821 } | 2833 } |
2822 | 2834 |
2823 if (cond_graph != NULL) { | 2835 if (cond_graph != NULL) { |
2824 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); | 2836 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph, |
| 2837 break_info.break_block()); |
2825 } else { | 2838 } else { |
2826 current_subgraph_->AppendEndless(body_graph, stmt); | 2839 subgraph()->AppendEndless(body_graph, stmt, break_info.break_block()); |
2827 } | 2840 } |
2828 } | 2841 } |
2829 | 2842 |
2830 | 2843 |
2831 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 2844 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
2832 BAILOUT("ForInStatement"); | 2845 BAILOUT("ForInStatement"); |
2833 } | 2846 } |
2834 | 2847 |
2835 | 2848 |
2836 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 2849 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
(...skipping 3221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6058 } | 6071 } |
6059 } | 6072 } |
6060 | 6073 |
6061 #ifdef DEBUG | 6074 #ifdef DEBUG |
6062 if (graph_ != NULL) graph_->Verify(); | 6075 if (graph_ != NULL) graph_->Verify(); |
6063 if (allocator_ != NULL) allocator_->Verify(); | 6076 if (allocator_ != NULL) allocator_->Verify(); |
6064 #endif | 6077 #endif |
6065 } | 6078 } |
6066 | 6079 |
6067 } } // namespace v8::internal | 6080 } } // namespace v8::internal |
OLD | NEW |