Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/bit_vector.h" | |
| 9 #include "vm/code_descriptors.h" | 10 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 11 #include "vm/flags.h" | 12 #include "vm/flags.h" |
| 12 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/il_printer.h" | 14 #include "vm/il_printer.h" |
| 14 #include "vm/intermediate_language.h" | 15 #include "vm/intermediate_language.h" |
| 15 #include "vm/longjump.h" | 16 #include "vm/longjump.h" |
| 16 #include "vm/object_store.h" | 17 #include "vm/object_store.h" |
| 17 #include "vm/os.h" | 18 #include "vm/os.h" |
| 18 #include "vm/parser.h" | 19 #include "vm/parser.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 36 | 37 |
| 37 static const String& PrivateCoreLibName(const String& str) { | 38 static const String& PrivateCoreLibName(const String& str) { |
| 38 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 39 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 39 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); | 40 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); |
| 40 return private_name; | 41 return private_name; |
| 41 } | 42 } |
| 42 | 43 |
| 43 | 44 |
| 44 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function, | 45 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function, |
| 45 const Array& ic_data_array, | 46 const Array& ic_data_array, |
| 46 InlineExitCollector* exit_collector) | 47 InlineExitCollector* exit_collector, |
| 48 intptr_t osr_id) | |
| 47 : parsed_function_(parsed_function), | 49 : parsed_function_(parsed_function), |
| 48 ic_data_array_(ic_data_array), | 50 ic_data_array_(ic_data_array), |
| 49 num_copied_params_(parsed_function->num_copied_params()), | 51 num_copied_params_(parsed_function->num_copied_params()), |
| 50 // All parameters are copied if any parameter is. | 52 // All parameters are copied if any parameter is. |
| 51 num_non_copied_params_((num_copied_params_ == 0) | 53 num_non_copied_params_((num_copied_params_ == 0) |
| 52 ? parsed_function->function().num_fixed_parameters() | 54 ? parsed_function->function().num_fixed_parameters() |
| 53 : 0), | 55 : 0), |
| 54 num_stack_locals_(parsed_function->num_stack_locals()), | 56 num_stack_locals_(parsed_function->num_stack_locals()), |
| 55 exit_collector_(exit_collector), | 57 exit_collector_(exit_collector), |
| 56 last_used_block_id_(0), // 0 is used for the graph entry. | 58 last_used_block_id_(0), // 0 is used for the graph entry. |
| 57 context_level_(0), | 59 context_level_(0), |
| 58 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), | 60 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
| 59 try_index_(CatchClauseNode::kInvalidTryIndex), | 61 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 60 graph_entry_(NULL), | 62 graph_entry_(NULL), |
| 61 args_pushed_(0) { } | 63 args_pushed_(0), |
| 64 osr_id_(osr_id) { } | |
| 62 | 65 |
| 63 | 66 |
| 64 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { | 67 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { |
| 65 graph_entry_->AddCatchEntry(entry); | 68 graph_entry_->AddCatchEntry(entry); |
| 66 } | 69 } |
| 67 | 70 |
| 68 | 71 |
| 69 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { | 72 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { |
| 70 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); | 73 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); |
| 71 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); | 74 ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id()); |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 470 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
| 468 true_exit->Goto(join); | 471 true_exit->Goto(join); |
| 469 false_exit->Goto(join); | 472 false_exit->Goto(join); |
| 470 exit_ = join; | 473 exit_ = join; |
| 471 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); | 474 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); |
| 472 temp_index_ = true_fragment.temp_index(); | 475 temp_index_ = true_fragment.temp_index(); |
| 473 } | 476 } |
| 474 } | 477 } |
| 475 | 478 |
| 476 | 479 |
| 477 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 480 void EffectGraphVisitor::TieLoop(intptr_t token_pos, |
| 481 const TestGraphVisitor& test_fragment, | |
| 478 const EffectGraphVisitor& body_fragment) { | 482 const EffectGraphVisitor& body_fragment) { |
| 479 // We have: a test graph fragment with zero, one, or two available exits; | 483 // We have: a test graph fragment with zero, one, or two available exits; |
| 480 // and an effect graph fragment with zero or one available exits. We want | 484 // and an effect graph fragment with zero or one available exits. We want |
| 481 // to append the 'while loop' consisting of the test graph fragment as | 485 // to append the 'while loop' consisting of the test graph fragment as |
| 482 // condition and the effect graph fragment as body. | 486 // condition and the effect graph fragment as body. |
| 483 ASSERT(is_open()); | 487 ASSERT(is_open()); |
| 484 | 488 |
| 485 // 1. Connect the body to the test if it is reachable, and if so record | 489 // 1. Connect the body to the test if it is reachable, and if so record |
| 486 // its exit (if any). | 490 // its exit (if any). |
| 487 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); | 491 BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor(); |
| 488 Instruction* body_exit = AppendFragment(body_entry, body_fragment); | 492 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
| 489 | 493 |
| 490 // 2. Connect the test to this graph, including the body if reachable and | 494 // 2. Connect the test to this graph, including the body if reachable and |
| 491 // using a fresh join node if the body is reachable and has an open exit. | 495 // using a fresh join node if the body is reachable and has an open exit. |
| 492 if (body_exit == NULL) { | 496 if (body_exit == NULL) { |
| 493 Append(test_fragment); | 497 Append(test_fragment); |
| 494 } else { | 498 } else { |
| 495 JoinEntryInstr* join = | 499 JoinEntryInstr* join = |
| 496 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 500 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
| 497 join->LinkTo(test_fragment.entry()); | 501 CheckStackOverflowInstr* check = |
| 502 new CheckStackOverflowInstr(token_pos, true); | |
| 503 join->LinkTo(check); | |
| 504 check->LinkTo(test_fragment.entry()); | |
| 498 Goto(join); | 505 Goto(join); |
| 499 body_exit->Goto(join); | 506 body_exit->Goto(join); |
| 500 } | 507 } |
| 501 | 508 |
| 502 // 3. Set the exit to the graph to be the false successor of the test, a | 509 // 3. Set the exit to the graph to be the false successor of the test, a |
| 503 // fresh target node | 510 // fresh target node |
| 504 | |
| 505 exit_ = test_fragment.CreateFalseSuccessor(); | 511 exit_ = test_fragment.CreateFalseSuccessor(); |
| 506 } | 512 } |
| 507 | 513 |
| 508 | 514 |
| 509 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { | 515 PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) { |
| 510 owner_->add_args_pushed(1); | 516 owner_->add_args_pushed(1); |
| 511 PushArgumentInstr* result = new PushArgumentInstr(value); | 517 PushArgumentInstr* result = new PushArgumentInstr(value); |
| 512 AddInstruction(result); | 518 AddInstruction(result); |
| 513 return result; | 519 return result; |
| 514 } | 520 } |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1595 // f) loop-exit-target | 1601 // f) loop-exit-target |
| 1596 // g) break-join (optional) | 1602 // g) break-join (optional) |
| 1597 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 1603 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
| 1598 TestGraphVisitor for_test(owner(), | 1604 TestGraphVisitor for_test(owner(), |
| 1599 temp_index(), | 1605 temp_index(), |
| 1600 node->condition()->token_pos()); | 1606 node->condition()->token_pos()); |
| 1601 node->condition()->Visit(&for_test); | 1607 node->condition()->Visit(&for_test); |
| 1602 ASSERT(!for_test.is_empty()); // Language spec. | 1608 ASSERT(!for_test.is_empty()); // Language spec. |
| 1603 | 1609 |
| 1604 EffectGraphVisitor for_body(owner(), temp_index()); | 1610 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1605 for_body.AddInstruction( | |
| 1606 new CheckStackOverflowInstr(node->token_pos())); | |
| 1607 node->body()->Visit(&for_body); | 1611 node->body()->Visit(&for_body); |
| 1608 | 1612 |
| 1609 // Labels are set after body traversal. | 1613 // Labels are set after body traversal. |
| 1610 SourceLabel* lbl = node->label(); | 1614 SourceLabel* lbl = node->label(); |
| 1611 ASSERT(lbl != NULL); | 1615 ASSERT(lbl != NULL); |
| 1612 JoinEntryInstr* join = lbl->join_for_continue(); | 1616 JoinEntryInstr* join = lbl->join_for_continue(); |
| 1613 if (join != NULL) { | 1617 if (join != NULL) { |
| 1614 if (for_body.is_open()) for_body.Goto(join); | 1618 if (for_body.is_open()) for_body.Goto(join); |
| 1615 for_body.exit_ = join; | 1619 for_body.exit_ = join; |
| 1616 } | 1620 } |
| 1617 TieLoop(for_test, for_body); | 1621 TieLoop(node->token_pos(), for_test, for_body); |
| 1618 join = lbl->join_for_break(); | 1622 join = lbl->join_for_break(); |
| 1619 if (join != NULL) { | 1623 if (join != NULL) { |
| 1620 Goto(join); | 1624 Goto(join); |
| 1621 exit_ = join; | 1625 exit_ = join; |
| 1622 } | 1626 } |
| 1623 } | 1627 } |
| 1624 | 1628 |
| 1625 | 1629 |
| 1626 // The fragment is composed as follows: | 1630 // The fragment is composed as follows: |
| 1627 // a) body-entry-join | 1631 // a) body-entry-join |
| 1628 // b) [ body ] | 1632 // b) [ body ] |
| 1629 // c) test-entry (continue-join or body-exit-target) | 1633 // c) test-entry (continue-join or body-exit-target) |
| 1630 // d) [ test-entry ] -> (back-target, loop-exit-target) | 1634 // d) [ test-entry ] -> (back-target, loop-exit-target) |
| 1631 // e) back-target -> (body-entry-join) | 1635 // e) back-target -> (body-entry-join) |
| 1632 // f) loop-exit-target | 1636 // f) loop-exit-target |
| 1633 // g) break-join | 1637 // g) break-join |
| 1634 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 1638 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 1635 // Traverse body first in order to generate continue and break labels. | 1639 // Traverse body first in order to generate continue and break labels. |
| 1636 EffectGraphVisitor for_body(owner(), temp_index()); | 1640 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1637 for_body.AddInstruction( | |
| 1638 new CheckStackOverflowInstr(node->token_pos())); | |
| 1639 node->body()->Visit(&for_body); | 1641 node->body()->Visit(&for_body); |
| 1640 | 1642 |
| 1641 TestGraphVisitor for_test(owner(), | 1643 TestGraphVisitor for_test(owner(), |
| 1642 temp_index(), | 1644 temp_index(), |
| 1643 node->condition()->token_pos()); | 1645 node->condition()->token_pos()); |
| 1644 node->condition()->Visit(&for_test); | 1646 node->condition()->Visit(&for_test); |
| 1645 ASSERT(is_open()); | 1647 ASSERT(is_open()); |
| 1646 | 1648 |
| 1647 // Tie do-while loop (test is after the body). | 1649 // Tie do-while loop (test is after the body). |
| 1648 JoinEntryInstr* body_entry_join = | 1650 JoinEntryInstr* body_entry_join = |
| 1649 new JoinEntryInstr(owner()->AllocateBlockId(), | 1651 new JoinEntryInstr(owner()->AllocateBlockId(), |
| 1650 owner()->try_index()); | 1652 owner()->try_index()); |
| 1651 Goto(body_entry_join); | 1653 Goto(body_entry_join); |
| 1652 Instruction* body_exit = AppendFragment(body_entry_join, for_body); | 1654 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
| 1653 | 1655 |
| 1654 JoinEntryInstr* join = node->label()->join_for_continue(); | 1656 JoinEntryInstr* join = node->label()->join_for_continue(); |
| 1655 if ((body_exit != NULL) || (join != NULL)) { | 1657 if ((body_exit != NULL) || (join != NULL)) { |
| 1656 if (join == NULL) { | 1658 if (join == NULL) { |
| 1657 join = new JoinEntryInstr(owner()->AllocateBlockId(), | 1659 join = new JoinEntryInstr(owner()->AllocateBlockId(), |
| 1658 owner()->try_index()); | 1660 owner()->try_index()); |
| 1659 } | 1661 } |
| 1660 join->LinkTo(for_test.entry()); | 1662 CheckStackOverflowInstr* check = |
| 1663 new CheckStackOverflowInstr(node->token_pos(), true); | |
| 1664 join->LinkTo(check); | |
| 1665 check->LinkTo(for_test.entry()); | |
| 1661 if (body_exit != NULL) { | 1666 if (body_exit != NULL) { |
| 1662 body_exit->Goto(join); | 1667 body_exit->Goto(join); |
| 1663 } | 1668 } |
| 1664 } | 1669 } |
| 1665 | 1670 |
| 1666 for_test.IfTrueGoto(body_entry_join); | 1671 for_test.IfTrueGoto(body_entry_join); |
| 1667 join = node->label()->join_for_break(); | 1672 join = node->label()->join_for_break(); |
| 1668 if (join == NULL) { | 1673 if (join == NULL) { |
| 1669 exit_ = for_test.CreateFalseSuccessor(); | 1674 exit_ = for_test.CreateFalseSuccessor(); |
| 1670 } else { | 1675 } else { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1687 // h) loop-exit-target | 1692 // h) loop-exit-target |
| 1688 // i) break-join | 1693 // i) break-join |
| 1689 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 1694 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 1690 EffectGraphVisitor for_initializer(owner(), temp_index()); | 1695 EffectGraphVisitor for_initializer(owner(), temp_index()); |
| 1691 node->initializer()->Visit(&for_initializer); | 1696 node->initializer()->Visit(&for_initializer); |
| 1692 Append(for_initializer); | 1697 Append(for_initializer); |
| 1693 ASSERT(is_open()); | 1698 ASSERT(is_open()); |
| 1694 | 1699 |
| 1695 // Compose body to set any jump labels. | 1700 // Compose body to set any jump labels. |
| 1696 EffectGraphVisitor for_body(owner(), temp_index()); | 1701 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1697 for_body.AddInstruction( | |
| 1698 new CheckStackOverflowInstr(node->token_pos())); | |
| 1699 node->body()->Visit(&for_body); | 1702 node->body()->Visit(&for_body); |
| 1700 | 1703 |
| 1701 // Join loop body, increment and compute their end instruction. | |
| 1702 ASSERT(!for_body.is_empty()); | |
| 1703 Instruction* loop_increment_end = NULL; | |
| 1704 EffectGraphVisitor for_increment(owner(), temp_index()); | 1704 EffectGraphVisitor for_increment(owner(), temp_index()); |
| 1705 node->increment()->Visit(&for_increment); | 1705 node->increment()->Visit(&for_increment); |
| 1706 | |
| 1707 // Join the loop body and increment and then tie the loop. | |
| 1706 JoinEntryInstr* join = node->label()->join_for_continue(); | 1708 JoinEntryInstr* join = node->label()->join_for_continue(); |
| 1707 if (join != NULL) { | 1709 if ((join != NULL) || for_body.is_open()) { |
| 1708 // Insert the join between the body and increment. | |
| 1709 if (for_body.is_open()) for_body.Goto(join); | |
| 1710 loop_increment_end = AppendFragment(join, for_increment); | |
| 1711 ASSERT(loop_increment_end != NULL); | |
| 1712 } else if (for_body.is_open()) { | |
| 1713 // Do not insert an extra basic block. | |
| 1714 for_body.Append(for_increment); | |
| 1715 loop_increment_end = for_body.exit(); | |
| 1716 // 'for_body' contains at least the stack check. | |
| 1717 ASSERT(loop_increment_end != NULL); | |
| 1718 } else { | |
| 1719 loop_increment_end = NULL; | |
| 1720 } | |
| 1721 | |
| 1722 // 'loop_increment_end' is NULL only if there is no join for continue and the | |
| 1723 // body is not open, i.e., no backward branch exists. | |
| 1724 if (loop_increment_end != NULL) { | |
| 1725 JoinEntryInstr* loop_start = | 1710 JoinEntryInstr* loop_start = |
| 1726 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 1711 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
| 1712 if (join != NULL) { | |
| 1713 if (for_body.is_open()) for_body.Goto(join); | |
| 1714 AppendFragment(join, for_increment); | |
| 1715 for_increment.Goto(loop_start); | |
| 1716 } else { | |
| 1717 for_body.Append(for_increment); | |
| 1718 for_body.Goto(loop_start); | |
| 1719 } | |
| 1727 Goto(loop_start); | 1720 Goto(loop_start); |
| 1728 loop_increment_end->Goto(loop_start); | |
| 1729 exit_ = loop_start; | 1721 exit_ = loop_start; |
| 1722 AddInstruction(new CheckStackOverflowInstr(node->token_pos(), true)); | |
| 1730 } | 1723 } |
| 1731 | 1724 |
| 1732 if (node->condition() == NULL) { | 1725 if (node->condition() == NULL) { |
| 1733 // Endless loop, no test. | 1726 // Endless loop, no test. |
| 1734 JoinEntryInstr* body_entry = | 1727 JoinEntryInstr* body_entry = |
| 1735 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 1728 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
| 1736 AppendFragment(body_entry, for_body); | 1729 AppendFragment(body_entry, for_body); |
| 1737 Goto(body_entry); | 1730 Goto(body_entry); |
| 1738 if (node->label()->join_for_break() != NULL) { | 1731 if (node->label()->join_for_break() != NULL) { |
| 1739 // Control flow of ForLoop continues into join_for_break. | 1732 // Control flow of ForLoop continues into join_for_break. |
| (...skipping 1715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3455 AppendFragment(finally_entry, for_finally_block); | 3448 AppendFragment(finally_entry, for_finally_block); |
| 3456 exit_ = for_finally_block.exit_; | 3449 exit_ = for_finally_block.exit_; |
| 3457 } | 3450 } |
| 3458 | 3451 |
| 3459 | 3452 |
| 3460 FlowGraph* FlowGraphBuilder::BuildGraph() { | 3453 FlowGraph* FlowGraphBuilder::BuildGraph() { |
| 3461 if (FLAG_print_ast) { | 3454 if (FLAG_print_ast) { |
| 3462 // Print the function ast before IL generation. | 3455 // Print the function ast before IL generation. |
| 3463 AstPrinter::PrintFunctionNodes(*parsed_function()); | 3456 AstPrinter::PrintFunctionNodes(*parsed_function()); |
| 3464 } | 3457 } |
| 3465 // Compilation can be nested, preserve the computation-id. | |
| 3466 const Function& function = parsed_function()->function(); | 3458 const Function& function = parsed_function()->function(); |
| 3467 TargetEntryInstr* normal_entry = | 3459 TargetEntryInstr* normal_entry = |
| 3468 new TargetEntryInstr(AllocateBlockId(), | 3460 new TargetEntryInstr(AllocateBlockId(), |
| 3469 CatchClauseNode::kInvalidTryIndex); | 3461 CatchClauseNode::kInvalidTryIndex); |
| 3470 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry); | 3462 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_); |
| 3471 EffectGraphVisitor for_effect(this, 0); | 3463 EffectGraphVisitor for_effect(this, 0); |
| 3472 // This check may be deleted if the generated code is leaf. | 3464 // This check may be deleted if the generated code is leaf. |
| 3473 CheckStackOverflowInstr* check = | 3465 CheckStackOverflowInstr* check = |
| 3474 new CheckStackOverflowInstr(function.token_pos()); | 3466 new CheckStackOverflowInstr(function.token_pos(), false); |
| 3475 // If we are inlining don't actually attach the stack check. We must still | 3467 // If we are inlining don't actually attach the stack check. We must still |
| 3476 // create the stack check in order to allocate a deopt id. | 3468 // create the stack check in order to allocate a deopt id. |
| 3477 if (!IsInlining()) for_effect.AddInstruction(check); | 3469 if (!IsInlining()) for_effect.AddInstruction(check); |
| 3478 parsed_function()->node_sequence()->Visit(&for_effect); | 3470 parsed_function()->node_sequence()->Visit(&for_effect); |
| 3479 AppendFragment(normal_entry, for_effect); | 3471 AppendFragment(normal_entry, for_effect); |
| 3480 // Check that the graph is properly terminated. | 3472 // Check that the graph is properly terminated. |
| 3481 ASSERT(!for_effect.is_open()); | 3473 ASSERT(!for_effect.is_open()); |
| 3474 | |
| 3475 // When compiling for OSR, use a depth first search to prune instructions | |
| 3476 // unreachable from the OSR entry. Catch entries are not (yet) properly | |
| 3477 // recognized as reachable. | |
| 3478 if (osr_id_ != Isolate::kNoDeoptId) { | |
| 3479 if (graph_entry_->SuccessorCount() > 1) { | |
| 3480 Bailout("try/catch when compiling for OSR"); | |
|
Florian Schneider
2013/06/12 08:25:24
Add a TODO to enable OSR for such functions. What
Kevin Millikin (Google)
2013/06/14 10:10:42
I think they might just work but generate unreacha
| |
| 3481 } | |
| 3482 PruneUnreachable(); | |
| 3483 } | |
| 3484 | |
| 3482 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); | 3485 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); |
| 3483 return graph; | 3486 return graph; |
| 3484 } | 3487 } |
| 3485 | 3488 |
| 3486 | 3489 |
| 3490 void FlowGraphBuilder::PruneUnreachable() { | |
| 3491 ASSERT(osr_id_ != Isolate::kNoDeoptId); | |
| 3492 BitVector* block_marks = new BitVector(last_used_block_id_ + 1); | |
| 3493 bool found = graph_entry_->PruneUnreachable(this, graph_entry_, osr_id_, | |
| 3494 block_marks); | |
| 3495 ASSERT(found); | |
| 3496 } | |
| 3497 | |
| 3498 | |
| 3487 void FlowGraphBuilder::Bailout(const char* reason) { | 3499 void FlowGraphBuilder::Bailout(const char* reason) { |
| 3488 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 3500 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 3489 const char* function_name = parsed_function_->function().ToCString(); | 3501 const char* function_name = parsed_function_->function().ToCString(); |
| 3490 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3502 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 3491 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3503 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 3492 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3504 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 3493 const Error& error = Error::Handle( | 3505 const Error& error = Error::Handle( |
| 3494 LanguageError::New(String::Handle(String::New(chars)))); | 3506 LanguageError::New(String::Handle(String::New(chars)))); |
| 3495 Isolate::Current()->long_jump_base()->Jump(1, error); | 3507 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 3496 } | 3508 } |
| 3497 | 3509 |
| 3498 | 3510 |
| 3499 } // namespace dart | 3511 } // namespace dart |
| OLD | NEW |