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