Index: src/interpreter/control-flow-builders.cc |
diff --git a/src/interpreter/control-flow-builders.cc b/src/interpreter/control-flow-builders.cc |
index 6510aa443aaa2a605989865596cc8227406d3a48..2cd2ba790fb343b5bd4e831d2d150246d349b4ee 100644 |
--- a/src/interpreter/control-flow-builders.cc |
+++ b/src/interpreter/control-flow-builders.cc |
@@ -97,6 +97,48 @@ void LoopBuilder::LoopHeader() { |
// and misplaced between the headers. |
DCHECK(break_sites_.empty() && continue_sites_.empty()); |
builder()->Bind(&loop_header_); |
+ |
+ if (yield_count > 0) { |
+ // Special treatment for loops containing yields (in generator functions). |
+ |
+ // Bind all labels for resume points within the loop to the loop header. |
+ // Also create fresh labels for these resume points, to be used inside the |
+ // loop. |
+ auto& resume_points = builder()->generator_resume_points; |
+ int yields_seen = builder()->generator_yields_seen(); |
+ for (int id = yields_seen; id < yields_seen + yield_count; id++) { |
+ DCHECK(0 <= id && id < resume_points.size()); |
+ builder()->Bind(loop_header_, &(resume_points[id])); |
+ resume_points[id] = BytecodeLabel(); |
+ } |
+ |
+ Register state = Register::new_target(); // HACK |
+ |
+ // If we are not resuming, fall through to loop body. |
+ // If we are resuming, perform state dispatch. |
+ BytecodeLabel not_resuming; |
+ builder() |
+ ->LoadLiteral(Smi::FromInt(yields_seen)) |
+ .CompareOperation(Token::Value::LT, state) |
+ .JumpIfTrue(¬_resuming) |
+ .IndexedJump(state, yields_seen, yield_count, resume_points) |
+ .Bind(¬_resuming); |
rmcilroy
2016/04/19 09:30:03
I really think this logic should live in the bytec
neis
2016/04/19 11:02:15
See my comments below.
|
+ } |
+} |
+ |
+ |
+void LoopBuilder::JumpToHeader() { |
+ if (yield_count > 0) { |
+ // Special treatment for loops containing yields (in generator functions). |
+ // Before jumping back to the loop header, set state to something that |
+ // will cause the next iteration to "not resume", i.e. to start from the |
+ // beginning. |
+ Register state = Register::new_target(); // HACK |
+ builder() |
+ ->LoadLiteral(Smi::FromInt(-1)) |
+ .StoreAccumulatorInRegister(state); |
rmcilroy
2016/04/19 09:30:03
Could we instead set the resume value to -1 at the
neis
2016/04/19 11:02:15
There is no "final" yield. Eg.:
while (...) {
.
rmcilroy
2016/04/19 11:14:26
Both of these are different yield points though, r
Jarin
2016/04/25 09:50:37
Indeed, I thought we set the state to -1 after the
|
+ } |
+ builder()->Jump(&loop_header_); |
} |