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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 9958070: Implement JumpNode handling (continue, break) in Dowhile and While nodes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_builder.cc
===================================================================
--- runtime/vm/flow_graph_builder.cc (revision 6094)
+++ runtime/vm/flow_graph_builder.cc (working copy)
@@ -713,56 +713,98 @@
// <Statement> ::= While { label: SourceLabel
// condition: <Expression>
// body: <Sequence> }
+// The fragment is composed as follows:
+// a) continue-join (optional)
+// b) loop-join
+// c) [ test ] -> (body-entry-target, loop-exit-target)
+// d) body-entry-target
+// e) [ body ] -> (loop-join)
+// f) loop-exit-target
+// g) break-join (optional)
void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
TestGraphVisitor for_test(owner(), temp_index());
node->condition()->Visit(&for_test);
+ ASSERT(!for_test.is_empty()); // Language spec.
EffectGraphVisitor for_body(owner(), temp_index());
node->body()->Visit(&for_body);
+
+ // Labels are set after body traversal.
+ SourceLabel* lbl = node->label();
+ ASSERT(lbl != NULL);
+ if (lbl->join_for_continue() != NULL) {
+ AddInstruction(lbl->join_for_continue());
+ }
TieLoop(for_test, for_body);
- // TODO(srdjan): Implement JumpNode handling.
- if ((node->label() != NULL) &&
- ((node->label()->join_for_break() != NULL) ||
- (node->label()->join_for_continue() != NULL))) {
- Bailout("Jump in WhileNode");
+ if (lbl->join_for_break() != NULL) {
+ AddInstruction(lbl->join_for_break());
}
}
+// The fragment is composed as follows:
+// a) body-entry-join
+// b) [ body ]
+// c) test-entry (continue-join or body-exit-target)
+// d) [ test-entry ] -> (back-target, loop-exit-target)
+// e) back-target -> (body-entry-join)
+// f) loop-exit-target
+// g) break-join
void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
+ // Traverse body first in order to generate continue and break labels.
EffectGraphVisitor for_body(owner(), temp_index());
node->body()->Visit(&for_body);
+
TestGraphVisitor for_test(owner(), temp_index());
node->condition()->Visit(&for_test);
ASSERT(is_open());
// Tie do-while loop (test is after the body).
- JoinEntryInstr* join = new JoinEntryInstr();
- AddInstruction(join);
- join->SetSuccessor(for_body.entry());
- Instruction* body_exit = for_body.is_empty() ? join : for_body.exit();
+ JoinEntryInstr* body_entry_join = new JoinEntryInstr();
+ AddInstruction(body_entry_join);
+ body_entry_join->SetSuccessor(for_body.entry());
+ Instruction* body_exit =
+ for_body.is_empty() ? body_entry_join : for_body.exit();
- if (body_exit != NULL) {
- TargetEntryInstr* target_entry = new TargetEntryInstr();
- target_entry->SetSuccessor(for_test.entry());
- body_exit->SetSuccessor(target_entry);
+ if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) {
+ BlockEntryInstr* test_entry = NULL;
+ if (node->label()->join_for_continue() == NULL) {
+ test_entry = new TargetEntryInstr();
+ } else {
+ test_entry = node->label()->join_for_continue();
+ }
+ test_entry->SetSuccessor(for_test.entry());
+ if (body_exit != NULL) {
+ body_exit->SetSuccessor(test_entry);
+ }
}
TargetEntryInstr* back_target_entry = new TargetEntryInstr();
*for_test.true_successor_address() = back_target_entry;
- back_target_entry->SetSuccessor(join);
- exit_ = *for_test.false_successor_address() = new TargetEntryInstr();
- // TODO(srdjan): Implement JumpNode handling.
- if ((node->label() != NULL) &&
- ((node->label()->join_for_break() != NULL) ||
- (node->label()->join_for_continue() != NULL))) {
- Bailout("Jump in DoWhileNode");
+ back_target_entry->SetSuccessor(body_entry_join);
+ TargetEntryInstr* loop_exit_target = new TargetEntryInstr();
+ *for_test.false_successor_address() = loop_exit_target;
+ if (node->label()->join_for_break() == NULL) {
+ exit_ = loop_exit_target;
+ } else {
+ loop_exit_target->SetSuccessor(node->label()->join_for_break());
+ exit_ = node->label()->join_for_break();
}
}
// A ForNode can contain break and continue jumps. 'break' joins to
-// ForNode exit, 'continue' joins at increment entry.
+// ForNode exit, 'continue' joins at increment entry. The fragment is composed
+// as follows:
+// a) [ initializer ]
+// b) loop-join
+// c) [ test ] -> (body-entry-target, loop-exit-target)
+// d) body-entry-target
+// e) [ body ]
+// f) continue-join (optional)
+// g) [ increment ] -> (loop-join)
+// h) loop-exit-target
+// i) break-join
void EffectGraphVisitor::VisitForNode(ForNode* node) {
EffectGraphVisitor for_initializer(owner(), temp_index());
node->initializer()->Visit(&for_initializer);
@@ -776,6 +818,7 @@
node->body()->Visit(&for_body);
// Join loop body, increment and compute their end instruction.
+ ASSERT(!for_body.is_empty());
Instruction* loop_increment_end = NULL;
EffectGraphVisitor for_increment(owner(), temp_index());
if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) {
@@ -783,6 +826,7 @@
node->increment()->Visit(&for_increment);
for_body.Append(for_increment);
loop_increment_end = for_body.exit();
+ // 'for_body' contains at least the TargetInstruction 'body_entry'.
ASSERT(loop_increment_end != NULL);
} else if (node->label()->join_for_continue() != NULL) {
// Insert join between body and increment.
@@ -793,6 +837,9 @@
node->increment()->Visit(&for_increment);
loop_increment_end = for_increment.exit();
ASSERT(loop_increment_end != NULL);
+ } else {
+ loop_increment_end = NULL;
+ ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL);
}
// 'loop_increment_end' is NULL only if there is no join for continue and the
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698