Chromium Code Reviews| Index: runtime/vm/scopes.cc |
| =================================================================== |
| --- runtime/vm/scopes.cc (revision 8858) |
| +++ runtime/vm/scopes.cc (working copy) |
| @@ -13,7 +13,9 @@ |
| const char* SourceLabel::kDefaultLabelName = ":L"; |
| +const char* LocalVariable::kSavedContextVarName = ":saved_entry_context_var"; |
| + |
| int SourceLabel::FunctionLevel() const { |
| ASSERT(owner() != NULL); |
| return owner()->function_level(); |
| @@ -28,6 +30,7 @@ |
| loop_level_(loop_level), |
| context_level_(LocalScope::kUnitializedContextLevel), |
| num_context_variables_(0), |
| + begin_token_index_(0), |
| end_token_index_(0), |
| variables_(), |
| labels_() { |
| @@ -180,24 +183,32 @@ |
| } |
| -RawLocalVarDescriptors* LocalScope::GetVarDescriptors() { |
| - GrowableArray<LocalVariable*> vars(8); |
| - // Variables of each scope are guaranteed to be consecutive elements |
| - // in array vars. See CollectLocalVariables() below. The outermost |
| - // scope (containing the function parameters) has id 0. |
| - CollectLocalVariables(&vars); |
| +RawLocalVarDescriptors* LocalScope::GetVarDescriptors(const Function& func) { |
| + GrowableArray<VarDesc> vars(8); |
| + // First enter all variables from scopes of outer functions. |
| + const ContextScope& context_scope = |
| + ContextScope::Handle(func.context_scope()); |
| + if (!context_scope.IsNull()) { |
| + ASSERT(func.IsLocalFunction()); |
| + for (int i = 0; i < context_scope.num_variables(); i++) { |
| + VarDesc desc; |
| + desc.name = &String::Handle(context_scope.NameAt(i)); |
| + desc.info.kind = RawLocalVarDescriptors::kContextVar; |
| + desc.info.scope_id = context_scope.ContextLevelAt(i); |
| + desc.info.begin_pos = begin_token_index(); |
| + desc.info.end_pos = end_token_index(); |
| + desc.info.index = context_scope.ContextIndexAt(i); |
| + vars.Add(desc); |
| + } |
| + } |
| + // Now collect all variables from local scopes. |
| + int16_t scope_id = 0; |
| + CollectLocalVariables(&vars, &scope_id); |
| + |
| const LocalVarDescriptors& var_desc = |
| LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars.length())); |
| - intptr_t scope_id = -1; |
| - LocalScope* current_scope = NULL; |
| - for (int i = 0; i < vars.length(); i++) { |
| - LocalVariable* var = vars[i]; |
| - if (current_scope != var->owner()) { |
| - current_scope = var->owner(); |
| - scope_id += 1; |
| - } |
| - var_desc.SetVar(i, var->name(), var->index(), |
| - scope_id, var->token_index(), var->owner()->end_token_index()); |
| + for (int i = 0; i < vars.length(); i++) { |
| + var_desc.SetVar(i, *(vars[i].name), &vars[i].info); |
| } |
| return var_desc.raw(); |
| } |
| @@ -205,22 +216,63 @@ |
| // Add variables that are declared in this scope to vars, then collect |
| // variables of children, followed by siblings. |
| -void LocalScope::CollectLocalVariables(GrowableArray<LocalVariable*>* vars) { |
| +void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars, |
| + int16_t* scope_id) { |
| + (*scope_id)++; |
| + if (HasContextLevel() && |
| + ((parent() == NULL) || |
| + (!parent()->HasContextLevel()) || |
|
regis
2012/06/19 18:14:41
No indentation needed.
hausner
2012/06/19 18:49:41
Ok. I try to indicate factors and terms by indenta
|
| + (parent()->context_level() != context_level()))) { |
| + // This is the outermost scope with a context level or this scope's |
| + // context level differes from its parent's level. |
| + VarDesc desc; |
| + desc.name = &String::Handle(); // No name. |
| + desc.info.kind = RawLocalVarDescriptors::kContextLevel; |
| + desc.info.scope_id = *scope_id; |
| + desc.info.begin_pos = begin_token_index(); |
| + desc.info.end_pos = end_token_index(); |
| + desc.info.index = context_level(); |
| + vars->Add(desc); |
| + } |
| for (int i = 0; i < this->variables_.length(); i++) { |
| LocalVariable* var = variables_[i]; |
| - // TODO(hausner): Remove the is_captured() condition once the debugger |
| - // can handle getting values of captured variables. |
| - if (!var->is_captured() && (var->owner() == this) && |
| - Scanner::IsIdent(var->name())) { |
| - vars->Add(this->variables_[i]); |
| + if (var->owner() == this) { |
| + if (Scanner::IsIdent(var->name())) { |
| + // This is a regular Dart variable, either stack-based or captured. |
| + VarDesc desc; |
| + desc.name = &var->name(); |
| + if (var->is_captured()) { |
| + desc.info.kind = RawLocalVarDescriptors::kContextVar; |
| + ASSERT(var->owner() != NULL); |
| + ASSERT(var->owner()->context_level() >= 0); |
| + desc.info.scope_id = var->owner()->context_level(); |
| + } else { |
| + desc.info.kind = RawLocalVarDescriptors::kStackVar; |
| + desc.info.scope_id = *scope_id; |
| + } |
| + desc.info.begin_pos = var->token_index(); |
| + desc.info.end_pos = var->owner()->end_token_index(); |
| + desc.info.index = var->index(); |
| + vars->Add(desc); |
| + } else if (var->name().Equals(LocalVariable::kSavedContextVarName)) { |
| + // This is the local variable in which the function saves the |
| + // caller's chain of closure contexts (caller's CTX register). |
| + VarDesc desc; |
| + desc.name = &var->name(); |
| + desc.info.kind = RawLocalVarDescriptors::kContextChain; |
| + desc.info.scope_id = 0; |
| + desc.info.begin_pos = 0; |
| + desc.info.end_pos = 0; |
| + desc.info.index = var->index(); |
| + vars->Add(desc); |
| + } |
| } |
| } |
| - if (child() != NULL) { |
| - child()->CollectLocalVariables(vars); |
| + LocalScope* child = this->child(); |
| + while (child != NULL) { |
| + child->CollectLocalVariables(vars, scope_id); |
| + child = child->sibling(); |
| } |
| - if (sibling() != NULL) { |
| - sibling()->CollectLocalVariables(vars); |
| - } |
| } |