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