OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/scopes.h" | 5 #include "vm/scopes.h" |
6 | 6 |
7 #include "vm/object.h" | 7 #include "vm/object.h" |
8 #include "vm/stack_frame.h" | 8 #include "vm/stack_frame.h" |
9 #include "vm/symbols.h" | 9 #include "vm/symbols.h" |
10 | 10 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 if (ref != NULL) { | 132 if (ref != NULL) { |
133 return ref->token_pos(); | 133 return ref->token_pos(); |
134 } | 134 } |
135 return -1; | 135 return -1; |
136 } | 136 } |
137 | 137 |
138 | 138 |
139 void LocalScope::AllocateContextVariable(LocalVariable* variable, | 139 void LocalScope::AllocateContextVariable(LocalVariable* variable, |
140 LocalScope** context_owner) { | 140 LocalScope** context_owner) { |
141 ASSERT(variable->is_captured()); | 141 ASSERT(variable->is_captured()); |
142 ASSERT(variable->owner()->loop_level() == loop_level()); | 142 ASSERT(variable->owner() == this); |
143 if (num_context_variables_ == 0) { | |
144 // This scope will allocate and chain a new context. | |
145 int new_context_level = ((*context_owner) == NULL) ? | |
146 1 : (*context_owner)->context_level() + 1; | |
147 // This scope becomes the current context owner. | |
148 *context_owner = this; | |
149 set_context_level(new_context_level); | |
150 } | |
151 // The context level in the owner scope of a captured variable indicates at | 143 // The context level in the owner scope of a captured variable indicates at |
152 // code generation time how far to walk up the context chain in order to | 144 // code generation time how far to walk up the context chain in order to |
153 // access the variable from the current context level. | 145 // access the variable from the current context level. |
154 if (!variable->owner()->HasContextLevel()) { | 146 if ((*context_owner) == NULL) { |
155 ASSERT(variable->owner() != this); | 147 ASSERT(num_context_variables_ == 0); |
156 variable->owner()->set_context_level(context_level()); | 148 // This scope becomes the current context owner. |
| 149 set_context_level(1); |
| 150 *context_owner = this; |
| 151 } else if ((*context_owner)->loop_level() < loop_level()) { |
| 152 // The captured variable is at a deeper loop level than the current context. |
| 153 // This scope will allocate and chain a new context. |
| 154 ASSERT(num_context_variables_ == 0); |
| 155 // This scope becomes the current context owner. |
| 156 set_context_level((*context_owner)->context_level() + 1); |
| 157 *context_owner = this; |
157 } else { | 158 } else { |
158 ASSERT(variable->owner()->context_level() == context_level()); | 159 // Allocate the captured variable in the current context. |
| 160 if (!HasContextLevel()) { |
| 161 ASSERT(variable->owner() != *context_owner); |
| 162 set_context_level((*context_owner)->context_level()); |
| 163 } else { |
| 164 ASSERT(context_level() == (*context_owner)->context_level()); |
| 165 } |
159 } | 166 } |
160 variable->set_index(num_context_variables_++); | 167 variable->set_index((*context_owner)->num_context_variables_++); |
161 } | 168 } |
162 | 169 |
163 | 170 |
164 int LocalScope::AllocateVariables(int first_parameter_index, | 171 int LocalScope::AllocateVariables(int first_parameter_index, |
165 int num_parameters, | 172 int num_parameters, |
166 int first_frame_index, | 173 int first_frame_index, |
167 LocalScope* loop_owner, | 174 LocalScope* context_owner, |
168 LocalScope** context_owner, | |
169 bool* found_captured_variables) { | 175 bool* found_captured_variables) { |
170 // We should not allocate variables of nested functions while compiling an | 176 // We should not allocate variables of nested functions while compiling an |
171 // enclosing function. | 177 // enclosing function. |
172 ASSERT(function_level() == 0); | 178 ASSERT(function_level() == 0); |
173 ASSERT(num_parameters >= 0); | 179 ASSERT(num_parameters >= 0); |
174 | |
175 // Keep track of the current loop owner scope, that is of the highest parent | |
176 // scope at the same loop level as this scope. | |
177 if (loop_level() > loop_owner->loop_level()) { | |
178 loop_owner = this; | |
179 } | |
180 // Parameters must be listed first and must all appear in the top scope. | 180 // Parameters must be listed first and must all appear in the top scope. |
181 ASSERT(num_parameters <= num_variables()); | 181 ASSERT(num_parameters <= num_variables()); |
182 int pos = 0; // Current variable position. | 182 int pos = 0; // Current variable position. |
183 int frame_index = first_parameter_index; // Current free frame index. | 183 int frame_index = first_parameter_index; // Current free frame index. |
184 while (pos < num_parameters) { | 184 while (pos < num_parameters) { |
185 LocalVariable* parameter = VariableAt(pos); | 185 LocalVariable* parameter = VariableAt(pos); |
186 pos++; | 186 pos++; |
187 // Parsing formal parameter default values may add local variable aliases | 187 // Parsing formal parameter default values may add local variable aliases |
188 // to the local scope before the formal parameters are added. However, | 188 // to the local scope before the formal parameters are added. However, |
189 // the parameters get inserted in front of the aliases, therefore, no | 189 // the parameters get inserted in front of the aliases, therefore, no |
190 // aliases can be encountered among the first num_parameters variables. | 190 // aliases can be encountered among the first num_parameters variables. |
191 ASSERT(parameter->owner() == this); | 191 ASSERT(parameter->owner() == this); |
192 if (parameter->is_captured()) { | 192 if (parameter->is_captured()) { |
193 // A captured parameter has a slot allocated in the frame and one in the | 193 // A captured parameter has a slot allocated in the frame and one in the |
194 // context, where it gets copied to. The parameter index reflects the | 194 // context, where it gets copied to. The parameter index reflects the |
195 // context allocation index. | 195 // context allocation index. |
196 frame_index--; | 196 frame_index--; |
197 loop_owner->AllocateContextVariable(parameter, context_owner); | 197 AllocateContextVariable(parameter, &context_owner); |
198 *found_captured_variables = true; | 198 *found_captured_variables = true; |
199 } else { | 199 } else { |
200 parameter->set_index(frame_index--); | 200 parameter->set_index(frame_index--); |
201 } | 201 } |
202 } | 202 } |
203 // No overlapping of parameters and locals. | 203 // No overlapping of parameters and locals. |
204 ASSERT(frame_index >= first_frame_index); | 204 ASSERT(frame_index >= first_frame_index); |
205 frame_index = first_frame_index; | 205 frame_index = first_frame_index; |
206 while (pos < num_variables()) { | 206 while (pos < num_variables()) { |
207 LocalVariable* variable = VariableAt(pos); | 207 LocalVariable* variable = VariableAt(pos); |
208 pos++; | 208 pos++; |
209 if (variable->owner() == this) { | 209 if (variable->owner() == this) { |
210 if (variable->is_captured()) { | 210 if (variable->is_captured()) { |
211 loop_owner->AllocateContextVariable(variable, context_owner); | 211 AllocateContextVariable(variable, &context_owner); |
212 *found_captured_variables = true; | 212 *found_captured_variables = true; |
213 } else { | 213 } else { |
214 variable->set_index(frame_index--); | 214 variable->set_index(frame_index--); |
215 } | 215 } |
216 } | 216 } |
217 } | 217 } |
218 // Allocate variables of all children. | 218 // Allocate variables of all children. |
219 int min_frame_index = frame_index; | 219 int min_frame_index = frame_index; // Frame index decreases with allocations. |
220 LocalScope* child = this->child(); | 220 LocalScope* child = this->child(); |
221 while (child != NULL) { | 221 while (child != NULL) { |
222 LocalScope* child_context_owner = *context_owner; | |
223 int const dummy_parameter_index = 0; // Ignored, since no parameters. | 222 int const dummy_parameter_index = 0; // Ignored, since no parameters. |
224 int const num_parameters_in_child = 0; // No parameters in children scopes. | 223 int const num_parameters_in_child = 0; // No parameters in children scopes. |
225 int child_frame_index = child->AllocateVariables(dummy_parameter_index, | 224 int child_frame_index = child->AllocateVariables(dummy_parameter_index, |
226 num_parameters_in_child, | 225 num_parameters_in_child, |
227 frame_index, | 226 frame_index, |
228 loop_owner, | 227 context_owner, |
229 &child_context_owner, | |
230 found_captured_variables); | 228 found_captured_variables); |
231 if (child_frame_index < min_frame_index) { | 229 if (child_frame_index < min_frame_index) { |
232 min_frame_index = child_frame_index; | 230 min_frame_index = child_frame_index; |
233 } | 231 } |
234 // A context allocated at a deeper loop level than the current loop level is | |
235 // not shared between children. | |
236 if ((child_context_owner != *context_owner) && | |
237 (child_context_owner->loop_level() <= loop_owner->loop_level())) { | |
238 *context_owner = child_context_owner; // Share context between siblings. | |
239 } | |
240 child = child->sibling(); | 232 child = child->sibling(); |
241 } | 233 } |
242 return min_frame_index; | 234 return min_frame_index; |
243 } | 235 } |
244 | 236 |
245 | 237 |
246 RawLocalVarDescriptors* LocalScope::GetVarDescriptors(const Function& func) { | 238 RawLocalVarDescriptors* LocalScope::GetVarDescriptors(const Function& func) { |
247 GrowableArray<VarDesc> vars(8); | 239 GrowableArray<VarDesc> vars(8); |
248 // First enter all variables from scopes of outer functions. | 240 // First enter all variables from scopes of outer functions. |
249 const ContextScope& context_scope = | 241 const ContextScope& context_scope = |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 return fixed_parameter_count - (index() - kParamEndSlotFromFp); | 653 return fixed_parameter_count - (index() - kParamEndSlotFromFp); |
662 } else { | 654 } else { |
663 // Shift negative indexes so that the lowest one is 0 (they are still | 655 // Shift negative indexes so that the lowest one is 0 (they are still |
664 // non-positive). | 656 // non-positive). |
665 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); | 657 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); |
666 } | 658 } |
667 } | 659 } |
668 | 660 |
669 | 661 |
670 } // namespace dart | 662 } // namespace dart |
OLD | NEW |