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 |