| 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 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 DEFINE_FLAG(bool, share_enclosing_context, true, | 13 DEFINE_FLAG(bool, |
| 14 share_enclosing_context, |
| 15 true, |
| 14 "Allocate captured variables in the existing context of an " | 16 "Allocate captured variables in the existing context of an " |
| 15 "enclosing scope (up to innermost loop) and spare the allocation " | 17 "enclosing scope (up to innermost loop) and spare the allocation " |
| 16 "of a local context."); | 18 "of a local context."); |
| 17 | 19 |
| 18 int SourceLabel::FunctionLevel() const { | 20 int SourceLabel::FunctionLevel() const { |
| 19 ASSERT(owner() != NULL); | 21 ASSERT(owner() != NULL); |
| 20 return owner()->function_level(); | 22 return owner()->function_level(); |
| 21 } | 23 } |
| 22 | 24 |
| 23 | 25 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 int num_parameters, | 196 int num_parameters, |
| 195 int first_frame_index, | 197 int first_frame_index, |
| 196 LocalScope* context_owner, | 198 LocalScope* context_owner, |
| 197 bool* found_captured_variables) { | 199 bool* found_captured_variables) { |
| 198 // We should not allocate variables of nested functions while compiling an | 200 // We should not allocate variables of nested functions while compiling an |
| 199 // enclosing function. | 201 // enclosing function. |
| 200 ASSERT(function_level() == 0); | 202 ASSERT(function_level() == 0); |
| 201 ASSERT(num_parameters >= 0); | 203 ASSERT(num_parameters >= 0); |
| 202 // Parameters must be listed first and must all appear in the top scope. | 204 // Parameters must be listed first and must all appear in the top scope. |
| 203 ASSERT(num_parameters <= num_variables()); | 205 ASSERT(num_parameters <= num_variables()); |
| 204 int pos = 0; // Current variable position. | 206 int pos = 0; // Current variable position. |
| 205 int frame_index = first_parameter_index; // Current free frame index. | 207 int frame_index = first_parameter_index; // Current free frame index. |
| 206 while (pos < num_parameters) { | 208 while (pos < num_parameters) { |
| 207 LocalVariable* parameter = VariableAt(pos); | 209 LocalVariable* parameter = VariableAt(pos); |
| 208 pos++; | 210 pos++; |
| 209 // Parsing formal parameter default values may add local variable aliases | 211 // Parsing formal parameter default values may add local variable aliases |
| 210 // to the local scope before the formal parameters are added. However, | 212 // to the local scope before the formal parameters are added. However, |
| 211 // the parameters get inserted in front of the aliases, therefore, no | 213 // the parameters get inserted in front of the aliases, therefore, no |
| 212 // aliases can be encountered among the first num_parameters variables. | 214 // aliases can be encountered among the first num_parameters variables. |
| 213 ASSERT(parameter->owner() == this); | 215 ASSERT(parameter->owner() == this); |
| 214 if (parameter->is_captured()) { | 216 if (parameter->is_captured()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 234 *found_captured_variables = true; | 236 *found_captured_variables = true; |
| 235 } else { | 237 } else { |
| 236 variable->set_index(frame_index--); | 238 variable->set_index(frame_index--); |
| 237 } | 239 } |
| 238 } | 240 } |
| 239 } | 241 } |
| 240 // Allocate variables of all children. | 242 // Allocate variables of all children. |
| 241 int min_frame_index = frame_index; // Frame index decreases with allocations. | 243 int min_frame_index = frame_index; // Frame index decreases with allocations. |
| 242 LocalScope* child = this->child(); | 244 LocalScope* child = this->child(); |
| 243 while (child != NULL) { | 245 while (child != NULL) { |
| 244 int const dummy_parameter_index = 0; // Ignored, since no parameters. | 246 int const dummy_parameter_index = 0; // Ignored, since no parameters. |
| 245 int const num_parameters_in_child = 0; // No parameters in children scopes. | 247 int const num_parameters_in_child = 0; // No parameters in children scopes. |
| 246 int child_frame_index = child->AllocateVariables(dummy_parameter_index, | 248 int child_frame_index = child->AllocateVariables( |
| 247 num_parameters_in_child, | 249 dummy_parameter_index, num_parameters_in_child, frame_index, |
| 248 frame_index, | 250 context_owner, found_captured_variables); |
| 249 context_owner, | |
| 250 found_captured_variables); | |
| 251 if (child_frame_index < min_frame_index) { | 251 if (child_frame_index < min_frame_index) { |
| 252 min_frame_index = child_frame_index; | 252 min_frame_index = child_frame_index; |
| 253 } | 253 } |
| 254 child = child->sibling(); | 254 child = child->sibling(); |
| 255 } | 255 } |
| 256 return min_frame_index; | 256 return min_frame_index; |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 // The parser creates internal variables that start with ":" | 260 // The parser creates internal variables that start with ":" |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 SourceLabel* LocalScope::LookupInnermostLabel(Token::Kind jump_kind) { | 455 SourceLabel* LocalScope::LookupInnermostLabel(Token::Kind jump_kind) { |
| 456 ASSERT((jump_kind == Token::kCONTINUE) || (jump_kind == Token::kBREAK)); | 456 ASSERT((jump_kind == Token::kCONTINUE) || (jump_kind == Token::kBREAK)); |
| 457 LocalScope* current_scope = this; | 457 LocalScope* current_scope = this; |
| 458 while (current_scope != NULL) { | 458 while (current_scope != NULL) { |
| 459 for (intptr_t i = 0; i < current_scope->labels_.length(); i++) { | 459 for (intptr_t i = 0; i < current_scope->labels_.length(); i++) { |
| 460 SourceLabel* label = current_scope->labels_[i]; | 460 SourceLabel* label = current_scope->labels_[i]; |
| 461 if ((label->kind() == SourceLabel::kWhile) || | 461 if ((label->kind() == SourceLabel::kWhile) || |
| 462 (label->kind() == SourceLabel::kFor) || | 462 (label->kind() == SourceLabel::kFor) || |
| 463 (label->kind() == SourceLabel::kDoWhile) || | 463 (label->kind() == SourceLabel::kDoWhile) || |
| 464 ((jump_kind == Token::kBREAK) && | 464 ((jump_kind == Token::kBREAK) && |
| 465 (label->kind() == SourceLabel::kSwitch))) { | 465 (label->kind() == SourceLabel::kSwitch))) { |
| 466 return label; | 466 return label; |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 current_scope = current_scope->parent(); | 469 current_scope = current_scope->parent(); |
| 470 } | 470 } |
| 471 return NULL; | 471 return NULL; |
| 472 } | 472 } |
| 473 | 473 |
| 474 | 474 |
| 475 LocalScope* LocalScope::LookupSwitchScope() { | 475 LocalScope* LocalScope::LookupSwitchScope() { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 if (variable->owner()->function_level() != 1) { | 526 if (variable->owner()->function_level() != 1) { |
| 527 ASSERT(variable->is_captured()); | 527 ASSERT(variable->is_captured()); |
| 528 ASSERT(variable->owner()->function_level() == 0); | 528 ASSERT(variable->owner()->function_level() == 0); |
| 529 num_captured++; | 529 num_captured++; |
| 530 } | 530 } |
| 531 } | 531 } |
| 532 return num_captured; | 532 return num_captured; |
| 533 } | 533 } |
| 534 | 534 |
| 535 | 535 |
| 536 RawContextScope* LocalScope::PreserveOuterScope(int current_context_level) | 536 RawContextScope* LocalScope::PreserveOuterScope( |
| 537 const { | 537 int current_context_level) const { |
| 538 // Since code generation for nested functions is postponed until first | 538 // Since code generation for nested functions is postponed until first |
| 539 // invocation, the function level of the closure scope can only be 1. | 539 // invocation, the function level of the closure scope can only be 1. |
| 540 ASSERT(function_level() == 1); | 540 ASSERT(function_level() == 1); |
| 541 | 541 |
| 542 // Count the number of referenced captured variables. | 542 // Count the number of referenced captured variables. |
| 543 intptr_t num_captured_vars = NumCapturedVariables(); | 543 intptr_t num_captured_vars = NumCapturedVariables(); |
| 544 | 544 |
| 545 // Create a ContextScope with space for num_captured_vars descriptors. | 545 // Create a ContextScope with space for num_captured_vars descriptors. |
| 546 const ContextScope& context_scope = | 546 const ContextScope& context_scope = |
| 547 ContextScope::Handle(ContextScope::New(num_captured_vars, false)); | 547 ContextScope::Handle(ContextScope::New(num_captured_vars, false)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 | 580 |
| 581 | 581 |
| 582 LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) { | 582 LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) { |
| 583 // The function level of the outer scope is one less than the function level | 583 // The function level of the outer scope is one less than the function level |
| 584 // of the current function, which is 0. | 584 // of the current function, which is 0. |
| 585 LocalScope* outer_scope = new LocalScope(NULL, -1, 0); | 585 LocalScope* outer_scope = new LocalScope(NULL, -1, 0); |
| 586 // Add all variables as aliases to the outer scope. | 586 // Add all variables as aliases to the outer scope. |
| 587 for (int i = 0; i < context_scope.num_variables(); i++) { | 587 for (int i = 0; i < context_scope.num_variables(); i++) { |
| 588 LocalVariable* variable; | 588 LocalVariable* variable; |
| 589 if (context_scope.IsConstAt(i)) { | 589 if (context_scope.IsConstAt(i)) { |
| 590 variable = new LocalVariable( | 590 variable = new LocalVariable(context_scope.DeclarationTokenIndexAt(i), |
| 591 context_scope.DeclarationTokenIndexAt(i), | 591 context_scope.TokenIndexAt(i), |
| 592 context_scope.TokenIndexAt(i), | 592 String::ZoneHandle(context_scope.NameAt(i)), |
| 593 String::ZoneHandle(context_scope.NameAt(i)), | 593 Object::dynamic_type()); |
| 594 Object::dynamic_type()); | |
| 595 variable->SetConstValue( | 594 variable->SetConstValue( |
| 596 Instance::ZoneHandle(context_scope.ConstValueAt(i))); | 595 Instance::ZoneHandle(context_scope.ConstValueAt(i))); |
| 597 } else { | 596 } else { |
| 598 variable = new LocalVariable( | 597 variable = |
| 599 context_scope.DeclarationTokenIndexAt(i), | 598 new LocalVariable(context_scope.DeclarationTokenIndexAt(i), |
| 600 context_scope.TokenIndexAt(i), | 599 context_scope.TokenIndexAt(i), |
| 601 String::ZoneHandle(context_scope.NameAt(i)), | 600 String::ZoneHandle(context_scope.NameAt(i)), |
| 602 AbstractType::ZoneHandle(context_scope.TypeAt(i))); | 601 AbstractType::ZoneHandle(context_scope.TypeAt(i))); |
| 603 } | 602 } |
| 604 variable->set_is_captured(); | 603 variable->set_is_captured(); |
| 605 variable->set_index(context_scope.ContextIndexAt(i)); | 604 variable->set_index(context_scope.ContextIndexAt(i)); |
| 606 if (context_scope.IsFinalAt(i)) { | 605 if (context_scope.IsFinalAt(i)) { |
| 607 variable->set_is_final(); | 606 variable->set_is_final(); |
| 608 } | 607 } |
| 609 // Create a fake owner scope describing the index and context level of the | 608 // Create a fake owner scope describing the index and context level of the |
| 610 // variable. Function level and loop level are unused (set to 0), since | 609 // variable. Function level and loop level are unused (set to 0), since |
| 611 // context level has already been assigned. | 610 // context level has already been assigned. |
| 612 LocalScope* owner_scope = new LocalScope(NULL, 0, 0); | 611 LocalScope* owner_scope = new LocalScope(NULL, 0, 0); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 return fixed_parameter_count - (index() - kParamEndSlotFromFp); | 686 return fixed_parameter_count - (index() - kParamEndSlotFromFp); |
| 688 } else { | 687 } else { |
| 689 // Shift negative indexes so that the lowest one is 0 (they are still | 688 // Shift negative indexes so that the lowest one is 0 (they are still |
| 690 // non-positive). | 689 // non-positive). |
| 691 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); | 690 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); |
| 692 } | 691 } |
| 693 } | 692 } |
| 694 | 693 |
| 695 | 694 |
| 696 } // namespace dart | 695 } // namespace dart |
| OLD | NEW |