Chromium Code Reviews| 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_); |
| } |