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

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 17315006: Scale the OSR optimization threshold by loop nesting depth. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (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/bit_vector.h"
10 #include "vm/code_descriptors.h" 10 #include "vm/code_descriptors.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 // All parameters are copied if any parameter is. 52 // All parameters are copied if any parameter is.
53 num_non_copied_params_((num_copied_params_ == 0) 53 num_non_copied_params_((num_copied_params_ == 0)
54 ? parsed_function->function().num_fixed_parameters() 54 ? parsed_function->function().num_fixed_parameters()
55 : 0), 55 : 0),
56 num_stack_locals_(parsed_function->num_stack_locals()), 56 num_stack_locals_(parsed_function->num_stack_locals()),
57 exit_collector_(exit_collector), 57 exit_collector_(exit_collector),
58 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.
59 context_level_(0), 59 context_level_(0),
60 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), 60 last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
61 try_index_(CatchClauseNode::kInvalidTryIndex), 61 try_index_(CatchClauseNode::kInvalidTryIndex),
62 loop_depth_(0),
62 graph_entry_(NULL), 63 graph_entry_(NULL),
63 args_pushed_(0), 64 args_pushed_(0),
64 osr_id_(osr_id) { } 65 osr_id_(osr_id) { }
65 66
66 67
67 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { 68 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
68 graph_entry_->AddCatchEntry(entry); 69 graph_entry_->AddCatchEntry(entry);
69 } 70 }
70 71
71 72
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 Instruction* body_exit = AppendFragment(body_entry, body_fragment); 493 Instruction* body_exit = AppendFragment(body_entry, body_fragment);
493 494
494 // 2. Connect the test to this graph, including the body if reachable and 495 // 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. 496 // using a fresh join node if the body is reachable and has an open exit.
496 if (body_exit == NULL) { 497 if (body_exit == NULL) {
497 Append(test_fragment); 498 Append(test_fragment);
498 } else { 499 } else {
499 JoinEntryInstr* join = 500 JoinEntryInstr* join =
500 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 501 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
501 CheckStackOverflowInstr* check = 502 CheckStackOverflowInstr* check =
502 new CheckStackOverflowInstr(token_pos, true); 503 new CheckStackOverflowInstr(token_pos, owner()->loop_depth());
503 join->LinkTo(check); 504 join->LinkTo(check);
504 check->LinkTo(test_fragment.entry()); 505 check->LinkTo(test_fragment.entry());
505 Goto(join); 506 Goto(join);
506 body_exit->Goto(join); 507 body_exit->Goto(join);
507 } 508 }
508 509
509 // 3. Set the exit to the graph to be the false successor of the test, a 510 // 3. Set the exit to the graph to be the false successor of the test, a
510 // fresh target node 511 // fresh target node
511 exit_ = test_fragment.CreateFalseSuccessor(); 512 exit_ = test_fragment.CreateFalseSuccessor();
512 } 513 }
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 // body: <Sequence> } 1595 // body: <Sequence> }
1595 // The fragment is composed as follows: 1596 // The fragment is composed as follows:
1596 // a) loop-join 1597 // a) loop-join
1597 // b) [ test ] -> (body-entry-target, loop-exit-target) 1598 // b) [ test ] -> (body-entry-target, loop-exit-target)
1598 // c) body-entry-target 1599 // c) body-entry-target
1599 // d) [ body ] -> (continue-join) 1600 // d) [ body ] -> (continue-join)
1600 // e) continue-join -> (loop-join) 1601 // e) continue-join -> (loop-join)
1601 // f) loop-exit-target 1602 // f) loop-exit-target
1602 // g) break-join (optional) 1603 // g) break-join (optional)
1603 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { 1604 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
1605 owner()->IncrementLoopDepth();
1604 TestGraphVisitor for_test(owner(), 1606 TestGraphVisitor for_test(owner(),
1605 temp_index(), 1607 temp_index(),
1606 node->condition()->token_pos()); 1608 node->condition()->token_pos());
1607 node->condition()->Visit(&for_test); 1609 node->condition()->Visit(&for_test);
1608 ASSERT(!for_test.is_empty()); // Language spec. 1610 ASSERT(!for_test.is_empty()); // Language spec.
1609 1611
1610 EffectGraphVisitor for_body(owner(), temp_index()); 1612 EffectGraphVisitor for_body(owner(), temp_index());
1611 node->body()->Visit(&for_body); 1613 node->body()->Visit(&for_body);
1612 1614
1613 // Labels are set after body traversal. 1615 // Labels are set after body traversal.
1614 SourceLabel* lbl = node->label(); 1616 SourceLabel* lbl = node->label();
1615 ASSERT(lbl != NULL); 1617 ASSERT(lbl != NULL);
1616 JoinEntryInstr* join = lbl->join_for_continue(); 1618 JoinEntryInstr* join = lbl->join_for_continue();
1617 if (join != NULL) { 1619 if (join != NULL) {
1618 if (for_body.is_open()) for_body.Goto(join); 1620 if (for_body.is_open()) for_body.Goto(join);
1619 for_body.exit_ = join; 1621 for_body.exit_ = join;
1620 } 1622 }
1621 TieLoop(node->token_pos(), for_test, for_body); 1623 TieLoop(node->token_pos(), for_test, for_body);
1622 join = lbl->join_for_break(); 1624 join = lbl->join_for_break();
1623 if (join != NULL) { 1625 if (join != NULL) {
1624 Goto(join); 1626 Goto(join);
1625 exit_ = join; 1627 exit_ = join;
1626 } 1628 }
1629 owner()->DecrementLoopDepth();
1627 } 1630 }
1628 1631
1629 1632
1630 // The fragment is composed as follows: 1633 // The fragment is composed as follows:
1631 // a) body-entry-join 1634 // a) body-entry-join
1632 // b) [ body ] 1635 // b) [ body ]
1633 // c) test-entry (continue-join or body-exit-target) 1636 // c) test-entry (continue-join or body-exit-target)
1634 // d) [ test-entry ] -> (back-target, loop-exit-target) 1637 // d) [ test-entry ] -> (back-target, loop-exit-target)
1635 // e) back-target -> (body-entry-join) 1638 // e) back-target -> (body-entry-join)
1636 // f) loop-exit-target 1639 // f) loop-exit-target
1637 // g) break-join 1640 // g) break-join
1638 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { 1641 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
1642 owner()->IncrementLoopDepth();
1639 // Traverse body first in order to generate continue and break labels. 1643 // Traverse body first in order to generate continue and break labels.
1640 EffectGraphVisitor for_body(owner(), temp_index()); 1644 EffectGraphVisitor for_body(owner(), temp_index());
1641 node->body()->Visit(&for_body); 1645 node->body()->Visit(&for_body);
1642 1646
1643 TestGraphVisitor for_test(owner(), 1647 TestGraphVisitor for_test(owner(),
1644 temp_index(), 1648 temp_index(),
1645 node->condition()->token_pos()); 1649 node->condition()->token_pos());
1646 node->condition()->Visit(&for_test); 1650 node->condition()->Visit(&for_test);
1647 ASSERT(is_open()); 1651 ASSERT(is_open());
1648 1652
1649 // Tie do-while loop (test is after the body). 1653 // Tie do-while loop (test is after the body).
1650 JoinEntryInstr* body_entry_join = 1654 JoinEntryInstr* body_entry_join =
1651 new JoinEntryInstr(owner()->AllocateBlockId(), 1655 new JoinEntryInstr(owner()->AllocateBlockId(),
1652 owner()->try_index()); 1656 owner()->try_index());
1653 Goto(body_entry_join); 1657 Goto(body_entry_join);
1654 Instruction* body_exit = AppendFragment(body_entry_join, for_body); 1658 Instruction* body_exit = AppendFragment(body_entry_join, for_body);
1655 1659
1656 JoinEntryInstr* join = node->label()->join_for_continue(); 1660 JoinEntryInstr* join = node->label()->join_for_continue();
1657 if ((body_exit != NULL) || (join != NULL)) { 1661 if ((body_exit != NULL) || (join != NULL)) {
1658 if (join == NULL) { 1662 if (join == NULL) {
1659 join = new JoinEntryInstr(owner()->AllocateBlockId(), 1663 join = new JoinEntryInstr(owner()->AllocateBlockId(),
1660 owner()->try_index()); 1664 owner()->try_index());
1661 } 1665 }
1662 CheckStackOverflowInstr* check = 1666 CheckStackOverflowInstr* check =
1663 new CheckStackOverflowInstr(node->token_pos(), true); 1667 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth());
1664 join->LinkTo(check); 1668 join->LinkTo(check);
1665 check->LinkTo(for_test.entry()); 1669 check->LinkTo(for_test.entry());
1666 if (body_exit != NULL) { 1670 if (body_exit != NULL) {
1667 body_exit->Goto(join); 1671 body_exit->Goto(join);
1668 } 1672 }
1669 } 1673 }
1670 1674
1671 for_test.IfTrueGoto(body_entry_join); 1675 for_test.IfTrueGoto(body_entry_join);
1672 join = node->label()->join_for_break(); 1676 join = node->label()->join_for_break();
1673 if (join == NULL) { 1677 if (join == NULL) {
1674 exit_ = for_test.CreateFalseSuccessor(); 1678 exit_ = for_test.CreateFalseSuccessor();
1675 } else { 1679 } else {
1676 for_test.IfFalseGoto(join); 1680 for_test.IfFalseGoto(join);
1677 exit_ = join; 1681 exit_ = join;
1678 } 1682 }
1683 owner()->DecrementLoopDepth();
1679 } 1684 }
1680 1685
1681 1686
1682 // A ForNode can contain break and continue jumps. 'break' joins to 1687 // A ForNode can contain break and continue jumps. 'break' joins to
1683 // ForNode exit, 'continue' joins at increment entry. The fragment is composed 1688 // ForNode exit, 'continue' joins at increment entry. The fragment is composed
1684 // as follows: 1689 // as follows:
1685 // a) [ initializer ] 1690 // a) [ initializer ]
1686 // b) loop-join 1691 // b) loop-join
1687 // c) [ test ] -> (body-entry-target, loop-exit-target) 1692 // c) [ test ] -> (body-entry-target, loop-exit-target)
1688 // d) body-entry-target 1693 // d) body-entry-target
1689 // e) [ body ] 1694 // e) [ body ]
1690 // f) continue-join (optional) 1695 // f) continue-join (optional)
1691 // g) [ increment ] -> (loop-join) 1696 // g) [ increment ] -> (loop-join)
1692 // h) loop-exit-target 1697 // h) loop-exit-target
1693 // i) break-join 1698 // i) break-join
1694 void EffectGraphVisitor::VisitForNode(ForNode* node) { 1699 void EffectGraphVisitor::VisitForNode(ForNode* node) {
1695 EffectGraphVisitor for_initializer(owner(), temp_index()); 1700 EffectGraphVisitor for_initializer(owner(), temp_index());
1696 node->initializer()->Visit(&for_initializer); 1701 node->initializer()->Visit(&for_initializer);
1697 Append(for_initializer); 1702 Append(for_initializer);
1698 ASSERT(is_open()); 1703 ASSERT(is_open());
1699 1704
1705 owner()->IncrementLoopDepth();
1700 // Compose body to set any jump labels. 1706 // Compose body to set any jump labels.
1701 EffectGraphVisitor for_body(owner(), temp_index()); 1707 EffectGraphVisitor for_body(owner(), temp_index());
1702 node->body()->Visit(&for_body); 1708 node->body()->Visit(&for_body);
1703 1709
1704 EffectGraphVisitor for_increment(owner(), temp_index()); 1710 EffectGraphVisitor for_increment(owner(), temp_index());
1705 node->increment()->Visit(&for_increment); 1711 node->increment()->Visit(&for_increment);
1706 1712
1707 // Join the loop body and increment and then tie the loop. 1713 // Join the loop body and increment and then tie the loop.
1708 JoinEntryInstr* join = node->label()->join_for_continue(); 1714 JoinEntryInstr* join = node->label()->join_for_continue();
1709 if ((join != NULL) || for_body.is_open()) { 1715 if ((join != NULL) || for_body.is_open()) {
1710 JoinEntryInstr* loop_start = 1716 JoinEntryInstr* loop_start =
1711 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 1717 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
1712 if (join != NULL) { 1718 if (join != NULL) {
1713 if (for_body.is_open()) for_body.Goto(join); 1719 if (for_body.is_open()) for_body.Goto(join);
1714 AppendFragment(join, for_increment); 1720 AppendFragment(join, for_increment);
1715 for_increment.Goto(loop_start); 1721 for_increment.Goto(loop_start);
1716 } else { 1722 } else {
1717 for_body.Append(for_increment); 1723 for_body.Append(for_increment);
1718 for_body.Goto(loop_start); 1724 for_body.Goto(loop_start);
1719 } 1725 }
1720 Goto(loop_start); 1726 Goto(loop_start);
1721 exit_ = loop_start; 1727 exit_ = loop_start;
1722 AddInstruction(new CheckStackOverflowInstr(node->token_pos(), true)); 1728 AddInstruction(
1729 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()));
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.
1733 exit_ = node->label()->join_for_break(); 1740 exit_ = node->label()->join_for_break();
1734 } 1741 }
1735 } else { 1742 } else {
1736 TestGraphVisitor for_test(owner(), 1743 TestGraphVisitor for_test(owner(),
1737 temp_index(), 1744 temp_index(),
1738 node->condition()->token_pos()); 1745 node->condition()->token_pos());
1739 node->condition()->Visit(&for_test); 1746 node->condition()->Visit(&for_test);
1740 Append(for_test); 1747 Append(for_test);
1741 1748
1742 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor(); 1749 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor();
1743 AppendFragment(body_entry, for_body); 1750 AppendFragment(body_entry, for_body);
1744 1751
1745 if (node->label()->join_for_break() == NULL) { 1752 if (node->label()->join_for_break() == NULL) {
1746 exit_ = for_test.CreateFalseSuccessor(); 1753 exit_ = for_test.CreateFalseSuccessor();
1747 } else { 1754 } else {
1748 for_test.IfFalseGoto(node->label()->join_for_break()); 1755 for_test.IfFalseGoto(node->label()->join_for_break());
1749 exit_ = node->label()->join_for_break(); 1756 exit_ = node->label()->join_for_break();
1750 } 1757 }
1751 } 1758 }
1759 owner()->DecrementLoopDepth();
1752 } 1760 }
1753 1761
1754 1762
1755 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { 1763 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
1756 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { 1764 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
1757 EffectGraphVisitor for_effect(owner(), temp_index()); 1765 EffectGraphVisitor for_effect(owner(), temp_index());
1758 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); 1766 node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
1759 Append(for_effect); 1767 Append(for_effect);
1760 if (!is_open()) return; 1768 if (!is_open()) return;
1761 } 1769 }
(...skipping 1695 matching lines...) Expand 10 before | Expand all | Expand 10 after
3457 AstPrinter::PrintFunctionNodes(*parsed_function()); 3465 AstPrinter::PrintFunctionNodes(*parsed_function());
3458 } 3466 }
3459 const Function& function = parsed_function()->function(); 3467 const Function& function = parsed_function()->function();
3460 TargetEntryInstr* normal_entry = 3468 TargetEntryInstr* normal_entry =
3461 new TargetEntryInstr(AllocateBlockId(), 3469 new TargetEntryInstr(AllocateBlockId(),
3462 CatchClauseNode::kInvalidTryIndex); 3470 CatchClauseNode::kInvalidTryIndex);
3463 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_); 3471 graph_entry_ = new GraphEntryInstr(*parsed_function(), normal_entry, osr_id_);
3464 EffectGraphVisitor for_effect(this, 0); 3472 EffectGraphVisitor for_effect(this, 0);
3465 // This check may be deleted if the generated code is leaf. 3473 // This check may be deleted if the generated code is leaf.
3466 CheckStackOverflowInstr* check = 3474 CheckStackOverflowInstr* check =
3467 new CheckStackOverflowInstr(function.token_pos(), false); 3475 new CheckStackOverflowInstr(function.token_pos(), 0);
3468 // If we are inlining don't actually attach the stack check. We must still 3476 // If we are inlining don't actually attach the stack check. We must still
3469 // create the stack check in order to allocate a deopt id. 3477 // create the stack check in order to allocate a deopt id.
3470 if (!IsInlining()) for_effect.AddInstruction(check); 3478 if (!IsInlining()) for_effect.AddInstruction(check);
3471 parsed_function()->node_sequence()->Visit(&for_effect); 3479 parsed_function()->node_sequence()->Visit(&for_effect);
3472 AppendFragment(normal_entry, for_effect); 3480 AppendFragment(normal_entry, for_effect);
3473 // Check that the graph is properly terminated. 3481 // Check that the graph is properly terminated.
3474 ASSERT(!for_effect.is_open()); 3482 ASSERT(!for_effect.is_open());
3475 3483
3476 // When compiling for OSR, use a depth first search to prune instructions 3484 // When compiling for OSR, use a depth first search to prune instructions
3477 // unreachable from the OSR entry. Catch entries are not (yet) properly 3485 // unreachable from the OSR entry. Catch entries are not (yet) properly
(...skipping 25 matching lines...) Expand all
3503 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3511 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3504 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3512 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3505 OS::SNPrint(chars, len, kFormat, function_name, reason); 3513 OS::SNPrint(chars, len, kFormat, function_name, reason);
3506 const Error& error = Error::Handle( 3514 const Error& error = Error::Handle(
3507 LanguageError::New(String::Handle(String::New(chars)))); 3515 LanguageError::New(String::Handle(String::New(chars))));
3508 Isolate::Current()->long_jump_base()->Jump(1, error); 3516 Isolate::Current()->long_jump_base()->Jump(1, error);
3509 } 3517 }
3510 3518
3511 3519
3512 } // namespace dart 3520 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698