| 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 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 } | 397 } |
| 398 } | 398 } |
| 399 return NULL; | 399 return NULL; |
| 400 } | 400 } |
| 401 | 401 |
| 402 | 402 |
| 403 LocalVariable* LocalScope::LookupVariable(const String& name, bool test_only) { | 403 LocalVariable* LocalScope::LookupVariable(const String& name, bool test_only) { |
| 404 LocalScope* current_scope = this; | 404 LocalScope* current_scope = this; |
| 405 while (current_scope != NULL) { | 405 while (current_scope != NULL) { |
| 406 LocalVariable* var = current_scope->LocalLookupVariable(name); | 406 LocalVariable* var = current_scope->LocalLookupVariable(name); |
| 407 if ((var != NULL) && !var->is_invisible_) { | 407 // If testing only, return the variable even if invisible. |
| 408 if (!test_only) { | 408 if ((var != NULL) && (!var->is_invisible_ || test_only)) { |
| 409 if (var->owner()->function_level() != function_level()) { | 409 if (!test_only && (var->owner()->function_level() != function_level())) { |
| 410 var->set_is_captured(); | 410 CaptureVariable(var); |
| 411 } | |
| 412 // Insert aliases of the variable in intermediate scopes. | |
| 413 LocalScope* intermediate_scope = this; | |
| 414 while (intermediate_scope != current_scope) { | |
| 415 intermediate_scope->variables_.Add(var); | |
| 416 ASSERT(var->owner() != intermediate_scope); // Item is an alias. | |
| 417 intermediate_scope = intermediate_scope->parent(); | |
| 418 } | |
| 419 } | 411 } |
| 420 return var; | 412 return var; |
| 421 } | 413 } |
| 422 current_scope = current_scope->parent(); | 414 current_scope = current_scope->parent(); |
| 423 } | 415 } |
| 424 return NULL; | 416 return NULL; |
| 425 } | 417 } |
| 426 | 418 |
| 427 | 419 |
| 428 bool LocalScope::CaptureVariable(const String& name) { | 420 void LocalScope::CaptureVariable(LocalVariable* variable) { |
| 429 ASSERT(name.IsSymbol()); | 421 ASSERT(variable != NULL); |
| 430 LocalScope* current_scope = this; | 422 // The variable must exist in an enclosing scope, not necessarily in this one. |
| 431 while (current_scope != NULL) { | 423 variable->set_is_captured(); |
| 432 LocalVariable* var = current_scope->LocalLookupVariable(name); | 424 const int variable_function_level = variable->owner()->function_level(); |
| 433 if (var != NULL) { | 425 LocalScope* scope = this; |
| 434 var->set_is_captured(); | 426 while (scope->function_level() != variable_function_level) { |
| 435 LocalScope* scope = this; | 427 // Insert an alias of the variable in the top scope of each function |
| 436 while (var->owner()->function_level() != scope->function_level()) { | 428 // level so that the variable is found in the context. |
| 437 // Insert an alias of the variable in the top scope of each function | 429 LocalScope* parent_scope = scope->parent(); |
| 438 // level so that the variable is found in the context. | 430 while ((parent_scope != NULL) && |
| 439 LocalScope* parent_scope = scope->parent(); | 431 (parent_scope->function_level() == scope->function_level())) { |
| 440 while ((parent_scope != NULL) && | 432 scope = parent_scope; |
| 441 (parent_scope->function_level() == scope->function_level())) { | 433 parent_scope = scope->parent(); |
| 442 scope = parent_scope; | |
| 443 parent_scope = scope->parent(); | |
| 444 } | |
| 445 scope->variables_.Add(var); | |
| 446 ASSERT(var->owner() != scope); // Item is an alias. | |
| 447 scope = parent_scope; | |
| 448 } | |
| 449 return true; | |
| 450 } | 434 } |
| 451 current_scope = current_scope->parent(); | 435 // An alias may already have been added in this scope, and in that case, |
| 436 // in parent scopes as needed. If so, we are done. |
| 437 if (!scope->AddVariable(variable)) { |
| 438 return; |
| 439 } |
| 440 ASSERT(variable->owner() != scope); // Item is an alias. |
| 441 scope = parent_scope; |
| 452 } | 442 } |
| 453 return false; | |
| 454 } | 443 } |
| 455 | 444 |
| 456 | 445 |
| 457 SourceLabel* LocalScope::LookupLabel(const String& name) { | 446 SourceLabel* LocalScope::LookupLabel(const String& name) { |
| 458 LocalScope* current_scope = this; | 447 LocalScope* current_scope = this; |
| 459 while (current_scope != NULL) { | 448 while (current_scope != NULL) { |
| 460 SourceLabel* label = current_scope->LocalLookupLabel(name); | 449 SourceLabel* label = current_scope->LocalLookupLabel(name); |
| 461 if (label != NULL) { | 450 if (label != NULL) { |
| 462 return label; | 451 return label; |
| 463 } | 452 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 outer_switch->AddLabel(label); | 507 outer_switch->AddLabel(label); |
| 519 } | 508 } |
| 520 } | 509 } |
| 521 } | 510 } |
| 522 return NULL; | 511 return NULL; |
| 523 } | 512 } |
| 524 | 513 |
| 525 | 514 |
| 526 int LocalScope::NumCapturedVariables() const { | 515 int LocalScope::NumCapturedVariables() const { |
| 527 // It is not necessary to traverse parent scopes, since we are only interested | 516 // It is not necessary to traverse parent scopes, since we are only interested |
| 528 // in the captured variables referenced in this scope. If this scope | 517 // in the captured variables referenced in this scope. If this scope is the |
| 529 // references a captured variable declared in a parent scope, it will contain | 518 // top scope at function level 1 and it (or its children scopes) references a |
| 530 // an alias for that variable. | 519 // captured variable declared in a parent scope at function level 0, it will |
| 520 // contain an alias for that variable. |
| 531 | 521 |
| 532 // Since code generation for nested functions is postponed until first | 522 // Since code generation for nested functions is postponed until first |
| 533 // invocation, the function level of the closure scope can only be 1. | 523 // invocation, the function level of the closure scope can only be 1. |
| 534 ASSERT(function_level() == 1); | 524 ASSERT(function_level() == 1); |
| 535 | 525 |
| 536 int num_captured = 0; | 526 int num_captured = 0; |
| 537 for (int i = 0; i < num_variables(); i++) { | 527 for (int i = 0; i < num_variables(); i++) { |
| 538 LocalVariable* variable = VariableAt(i); | 528 LocalVariable* variable = VariableAt(i); |
| 539 // Count the aliases of captured variables belonging to outer scopes. | 529 // Count the aliases of captured variables belonging to outer scopes. |
| 540 if (variable->owner()->function_level() != 1) { | 530 if (variable->owner()->function_level() != 1) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 owner_scope->set_context_level(context_scope.ContextLevelAt(i)); | 611 owner_scope->set_context_level(context_scope.ContextLevelAt(i)); |
| 622 owner_scope->AddVariable(variable); | 612 owner_scope->AddVariable(variable); |
| 623 outer_scope->AddVariable(variable); // As alias. | 613 outer_scope->AddVariable(variable); // As alias. |
| 624 ASSERT(variable->owner() == owner_scope); | 614 ASSERT(variable->owner() == owner_scope); |
| 625 } | 615 } |
| 626 return outer_scope; | 616 return outer_scope; |
| 627 } | 617 } |
| 628 | 618 |
| 629 | 619 |
| 630 void LocalScope::RecursivelyCaptureAllVariables() { | 620 void LocalScope::RecursivelyCaptureAllVariables() { |
| 631 bool found = false; | |
| 632 for (intptr_t i = 0; i < num_variables(); i++) { | 621 for (intptr_t i = 0; i < num_variables(); i++) { |
| 633 if ((VariableAt(i)->name().raw() == Symbols::StackTraceVar().raw()) || | 622 if ((VariableAt(i)->name().raw() == Symbols::StackTraceVar().raw()) || |
| 634 (VariableAt(i)->name().raw() == Symbols::ExceptionVar().raw()) || | 623 (VariableAt(i)->name().raw() == Symbols::ExceptionVar().raw()) || |
| 635 (VariableAt(i)->name().raw() == Symbols::SavedTryContextVar().raw())) { | 624 (VariableAt(i)->name().raw() == Symbols::SavedTryContextVar().raw())) { |
| 636 // Don't capture those variables because the VM expects them to be on the | 625 // Don't capture those variables because the VM expects them to be on the |
| 637 // stack. | 626 // stack. |
| 638 continue; | 627 continue; |
| 639 } | 628 } |
| 640 found = CaptureVariable(VariableAt(i)->name()); | 629 CaptureVariable(VariableAt(i)); |
| 641 ASSERT(found); | |
| 642 } | 630 } |
| 643 if (sibling() != NULL) { sibling()->RecursivelyCaptureAllVariables(); } | 631 if (sibling() != NULL) { sibling()->RecursivelyCaptureAllVariables(); } |
| 644 if (child() != NULL) { child()->RecursivelyCaptureAllVariables(); } | 632 if (child() != NULL) { child()->RecursivelyCaptureAllVariables(); } |
| 645 } | 633 } |
| 646 | 634 |
| 647 | 635 |
| 648 RawContextScope* LocalScope::CreateImplicitClosureScope(const Function& func) { | 636 RawContextScope* LocalScope::CreateImplicitClosureScope(const Function& func) { |
| 649 static const intptr_t kNumCapturedVars = 1; | 637 static const intptr_t kNumCapturedVars = 1; |
| 650 | 638 |
| 651 // Create a ContextScope with space for kNumCapturedVars descriptors. | 639 // Create a ContextScope with space for kNumCapturedVars descriptors. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 return fixed_parameter_count - (index() - kParamEndSlotFromFp); | 679 return fixed_parameter_count - (index() - kParamEndSlotFromFp); |
| 692 } else { | 680 } else { |
| 693 // Shift negative indexes so that the lowest one is 0 (they are still | 681 // Shift negative indexes so that the lowest one is 0 (they are still |
| 694 // non-positive). | 682 // non-positive). |
| 695 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); | 683 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); |
| 696 } | 684 } |
| 697 } | 685 } |
| 698 | 686 |
| 699 | 687 |
| 700 } // namespace dart | 688 } // namespace dart |
| OLD | NEW |