Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/control-flow-builders.h" | 5 #include "src/interpreter/control-flow-builders.h" |
| 6 | 6 |
| 7 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace interpreter { | 9 namespace interpreter { |
| 10 | 10 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 90 LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); } | 90 LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); } |
| 91 | 91 |
| 92 | 92 |
| 93 void LoopBuilder::LoopHeader() { | 93 void LoopBuilder::LoopHeader() { |
| 94 // Jumps from before the loop header into the loop violate ordering | 94 // Jumps from before the loop header into the loop violate ordering |
| 95 // requirements of bytecode basic blocks. The only entry into a loop | 95 // requirements of bytecode basic blocks. The only entry into a loop |
| 96 // must be the loop header. Surely breaks is okay? Not if nested | 96 // must be the loop header. Surely breaks is okay? Not if nested |
| 97 // and misplaced between the headers. | 97 // and misplaced between the headers. |
| 98 DCHECK(break_sites_.empty() && continue_sites_.empty()); | 98 DCHECK(break_sites_.empty() && continue_sites_.empty()); |
| 99 builder()->Bind(&loop_header_); | 99 builder()->Bind(&loop_header_); |
| 100 | |
| 101 if (yield_count > 0) { | |
| 102 // Special treatment for loops containing yields (in generator functions). | |
| 103 | |
| 104 // Bind all labels for resume points within the loop to the loop header. | |
| 105 // Also create fresh labels for these resume points, to be used inside the | |
| 106 // loop. | |
| 107 auto& resume_points = builder()->generator_resume_points; | |
| 108 int yields_seen = builder()->generator_yields_seen(); | |
| 109 for (int id = yields_seen; id < yields_seen + yield_count; id++) { | |
| 110 DCHECK(0 <= id && id < resume_points.size()); | |
| 111 builder()->Bind(loop_header_, &(resume_points[id])); | |
| 112 resume_points[id] = BytecodeLabel(); | |
| 113 } | |
| 114 | |
| 115 Register state = Register::new_target(); // HACK | |
| 116 | |
| 117 // If we are not resuming, fall through to loop body. | |
| 118 // If we are resuming, perform state dispatch. | |
| 119 BytecodeLabel not_resuming; | |
| 120 builder() | |
| 121 ->LoadLiteral(Smi::FromInt(yields_seen)) | |
| 122 .CompareOperation(Token::Value::LT, state) | |
| 123 .JumpIfTrue(¬_resuming) | |
| 124 .IndexedJump(state, yields_seen, yield_count, resume_points) | |
| 125 .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.
| |
| 126 } | |
| 100 } | 127 } |
| 101 | 128 |
| 102 | 129 |
| 130 void LoopBuilder::JumpToHeader() { | |
| 131 if (yield_count > 0) { | |
| 132 // Special treatment for loops containing yields (in generator functions). | |
| 133 // Before jumping back to the loop header, set state to something that | |
| 134 // will cause the next iteration to "not resume", i.e. to start from the | |
| 135 // beginning. | |
| 136 Register state = Register::new_target(); // HACK | |
| 137 builder() | |
| 138 ->LoadLiteral(Smi::FromInt(-1)) | |
| 139 .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
| |
| 140 } | |
| 141 builder()->Jump(&loop_header_); | |
| 142 } | |
| 143 | |
| 144 | |
| 103 void LoopBuilder::EndLoop() { | 145 void LoopBuilder::EndLoop() { |
| 104 // Loop must have closed form, i.e. all loop elements are within the loop, | 146 // Loop must have closed form, i.e. all loop elements are within the loop, |
| 105 // the loop header precedes the body and next elements in the loop. | 147 // the loop header precedes the body and next elements in the loop. |
| 106 DCHECK(loop_header_.is_bound()); | 148 DCHECK(loop_header_.is_bound()); |
| 107 builder()->Bind(&loop_end_); | 149 builder()->Bind(&loop_end_); |
| 108 SetBreakTarget(loop_end_); | 150 SetBreakTarget(loop_end_); |
| 109 if (next_.is_bound()) { | 151 if (next_.is_bound()) { |
| 110 DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset()); | 152 DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset()); |
| 111 SetContinueTarget(next_); | 153 SetContinueTarget(next_); |
| 112 } else { | 154 } else { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 } | 226 } |
| 185 | 227 |
| 186 | 228 |
| 187 void TryFinallyBuilder::EndFinally() { | 229 void TryFinallyBuilder::EndFinally() { |
| 188 // Nothing to be done here. | 230 // Nothing to be done here. |
| 189 } | 231 } |
| 190 | 232 |
| 191 } // namespace interpreter | 233 } // namespace interpreter |
| 192 } // namespace internal | 234 } // namespace internal |
| 193 } // namespace v8 | 235 } // namespace v8 |
| OLD | NEW |