| 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 |