Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 variables_(), | 122 variables_(), |
| 123 temps_(4), | 123 temps_(4), |
| 124 params_(4), | 124 params_(4), |
| 125 unresolved_(16), | 125 unresolved_(16), |
| 126 decls_(4), | 126 decls_(4), |
| 127 already_resolved_(false) { | 127 already_resolved_(false) { |
| 128 SetDefaults(type, outer_scope, Handle<ScopeInfo>::null()); | 128 SetDefaults(type, outer_scope, Handle<ScopeInfo>::null()); |
| 129 // At some point we might want to provide outer scopes to | 129 // At some point we might want to provide outer scopes to |
| 130 // eval scopes (by walking the stack and reading the scope info). | 130 // eval scopes (by walking the stack and reading the scope info). |
| 131 // In that case, the ASSERT below needs to be adjusted. | 131 // In that case, the ASSERT below needs to be adjusted. |
| 132 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); | 132 ASSERT((type == GLOBAL_SCOPE) == (outer_scope == NULL)); |
|
fschneider
2011/11/14 15:20:52
Use ASSERT_EQ instead, so that you get a better er
Steven
2011/11/15 11:53:23
Done.
| |
| 133 ASSERT(!HasIllegalRedeclaration()); | 133 ASSERT(!HasIllegalRedeclaration()); |
| 134 } | 134 } |
| 135 | 135 |
| 136 | 136 |
| 137 Scope::Scope(Scope* inner_scope, | 137 Scope::Scope(Scope* inner_scope, |
| 138 ScopeType type, | 138 ScopeType type, |
| 139 Handle<ScopeInfo> scope_info) | 139 Handle<ScopeInfo> scope_info) |
| 140 : isolate_(Isolate::Current()), | 140 : isolate_(Isolate::Current()), |
| 141 inner_scopes_(4), | 141 inner_scopes_(4), |
| 142 variables_(), | 142 variables_(), |
| 143 temps_(4), | 143 temps_(4), |
| 144 params_(4), | 144 params_(4), |
| 145 unresolved_(16), | 145 unresolved_(16), |
| 146 decls_(4), | 146 decls_(4), |
| 147 already_resolved_(true) { | 147 already_resolved_(true) { |
| 148 SetDefaults(type, NULL, scope_info); | 148 SetDefaults(type, NULL, scope_info); |
| 149 if (!scope_info.is_null()) { | 149 if (!scope_info.is_null()) { |
| 150 num_heap_slots_ = scope_info_->ContextLength(); | 150 num_heap_slots_ = scope_info_->ContextLength(); |
| 151 } else if (is_with_scope()) { | |
| 152 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | |
| 151 } | 153 } |
| 152 AddInnerScope(inner_scope); | 154 AddInnerScope(inner_scope); |
| 153 } | 155 } |
| 154 | 156 |
| 155 | 157 |
| 156 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) | 158 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) |
| 157 : isolate_(Isolate::Current()), | 159 : isolate_(Isolate::Current()), |
| 158 inner_scopes_(1), | 160 inner_scopes_(1), |
| 159 variables_(), | 161 variables_(), |
| 160 temps_(0), | 162 temps_(0), |
| 161 params_(0), | 163 params_(0), |
| 162 unresolved_(0), | 164 unresolved_(0), |
| 163 decls_(0), | 165 decls_(0), |
| 164 already_resolved_(true) { | 166 already_resolved_(true) { |
| 165 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); | 167 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
| 166 AddInnerScope(inner_scope); | 168 AddInnerScope(inner_scope); |
| 167 ++num_var_or_const_; | 169 ++num_var_or_const_; |
| 170 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | |
| 168 Variable* variable = variables_.Declare(this, | 171 Variable* variable = variables_.Declare(this, |
| 169 catch_variable_name, | 172 catch_variable_name, |
| 170 VAR, | 173 VAR, |
| 171 true, // Valid left-hand side. | 174 true, // Valid left-hand side. |
| 172 Variable::NORMAL, | 175 Variable::NORMAL, |
| 173 kCreatedInitialized); | 176 kCreatedInitialized); |
| 174 AllocateHeapSlot(variable); | 177 AllocateHeapSlot(variable); |
| 175 } | 178 } |
| 176 | 179 |
| 177 | 180 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 194 ? outer_scope->strict_mode_flag_ : kNonStrictMode; | 197 ? outer_scope->strict_mode_flag_ : kNonStrictMode; |
| 195 outer_scope_calls_non_strict_eval_ = false; | 198 outer_scope_calls_non_strict_eval_ = false; |
| 196 inner_scope_calls_eval_ = false; | 199 inner_scope_calls_eval_ = false; |
| 197 force_eager_compilation_ = false; | 200 force_eager_compilation_ = false; |
| 198 num_var_or_const_ = 0; | 201 num_var_or_const_ = 0; |
| 199 num_stack_slots_ = 0; | 202 num_stack_slots_ = 0; |
| 200 num_heap_slots_ = 0; | 203 num_heap_slots_ = 0; |
| 201 scope_info_ = scope_info; | 204 scope_info_ = scope_info; |
| 202 start_position_ = RelocInfo::kNoPosition; | 205 start_position_ = RelocInfo::kNoPosition; |
| 203 end_position_ = RelocInfo::kNoPosition; | 206 end_position_ = RelocInfo::kNoPosition; |
| 207 if (!scope_info.is_null()) { | |
| 208 scope_calls_eval_ = scope_info->CallsEval(); | |
| 209 strict_mode_flag_ = | |
| 210 scope_info->IsStrictMode() ? kStrictMode : kNonStrictMode; | |
| 211 } | |
| 204 } | 212 } |
| 205 | 213 |
| 206 | 214 |
| 207 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, | 215 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope) { |
| 208 Scope* global_scope) { | |
| 209 // Reconstruct the outer scope chain from a closure's context chain. | 216 // Reconstruct the outer scope chain from a closure's context chain. |
| 210 ASSERT(!info->closure().is_null()); | |
| 211 Context* context = info->closure()->context(); | |
| 212 Scope* current_scope = NULL; | 217 Scope* current_scope = NULL; |
| 213 Scope* innermost_scope = NULL; | 218 Scope* innermost_scope = NULL; |
| 214 bool contains_with = false; | 219 bool contains_with = false; |
| 215 while (!context->IsGlobalContext()) { | 220 while (!context->IsGlobalContext()) { |
| 216 if (context->IsWithContext()) { | 221 if (context->IsWithContext()) { |
| 217 Scope* with_scope = new Scope(current_scope, | 222 Scope* with_scope = new Scope(current_scope, |
| 218 WITH_SCOPE, | 223 WITH_SCOPE, |
| 219 Handle<ScopeInfo>::null()); | 224 Handle<ScopeInfo>::null()); |
| 220 current_scope = with_scope; | 225 current_scope = with_scope; |
| 221 // All the inner scopes are inside a with. | 226 // All the inner scopes are inside a with. |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 242 if (innermost_scope == NULL) innermost_scope = current_scope; | 247 if (innermost_scope == NULL) innermost_scope = current_scope; |
| 243 | 248 |
| 244 // Forget about a with when we move to a context for a different function. | 249 // Forget about a with when we move to a context for a different function. |
| 245 if (context->previous()->closure() != context->closure()) { | 250 if (context->previous()->closure() != context->closure()) { |
| 246 contains_with = false; | 251 contains_with = false; |
| 247 } | 252 } |
| 248 context = context->previous(); | 253 context = context->previous(); |
| 249 } | 254 } |
| 250 | 255 |
| 251 global_scope->AddInnerScope(current_scope); | 256 global_scope->AddInnerScope(current_scope); |
| 257 global_scope->PropagateScopeInfo(false); | |
| 252 return (innermost_scope == NULL) ? global_scope : innermost_scope; | 258 return (innermost_scope == NULL) ? global_scope : innermost_scope; |
| 253 } | 259 } |
| 254 | 260 |
| 255 | 261 |
| 256 bool Scope::Analyze(CompilationInfo* info) { | 262 bool Scope::Analyze(CompilationInfo* info) { |
| 257 ASSERT(info->function() != NULL); | 263 ASSERT(info->function() != NULL); |
| 258 Scope* top = info->function()->scope(); | 264 Scope* scope = info->function()->scope(); |
| 265 Scope* top = scope; | |
| 259 | 266 |
| 260 while (top->outer_scope() != NULL) top = top->outer_scope(); | 267 // Traverse the scope tree up to the first unresolved scope. |
| 261 top->AllocateVariables(info->calling_context()); | 268 while (!top->is_global_scope() && |
| 269 !top->outer_scope()->already_resolved()) { | |
|
fschneider
2011/11/14 15:20:52
This loop condition seems inconsistent with the co
Steven
2011/11/15 11:53:23
I've updated the comment with a more thorough desc
fschneider
2011/11/15 12:06:46
Maybe say: Traverse until the first unresolved sco
Steven
2011/11/15 13:51:15
Done.
| |
| 270 top = top->outer_scope(); | |
| 271 } | |
| 272 | |
| 273 // Allocated the variables. | |
| 274 top->AllocateVariables(info->global_scope()); | |
| 262 | 275 |
| 263 #ifdef DEBUG | 276 #ifdef DEBUG |
| 264 if (info->isolate()->bootstrapper()->IsActive() | 277 if (info->isolate()->bootstrapper()->IsActive() |
| 265 ? FLAG_print_builtin_scopes | 278 ? FLAG_print_builtin_scopes |
| 266 : FLAG_print_scopes) { | 279 : FLAG_print_scopes) { |
| 267 info->function()->scope()->Print(); | 280 scope->Print(); |
| 268 } | 281 } |
| 269 #endif | 282 #endif |
| 270 | 283 |
| 271 info->SetScope(info->function()->scope()); | 284 info->SetScope(scope); |
| 272 return true; // Can not fail. | 285 return true; // Can not fail. |
| 273 } | 286 } |
| 274 | 287 |
| 275 | 288 |
| 276 void Scope::Initialize() { | 289 void Scope::Initialize() { |
| 277 ASSERT(!already_resolved()); | 290 ASSERT(!already_resolved()); |
| 278 | 291 |
| 279 // Add this scope as a new inner scope of the outer scope. | 292 // Add this scope as a new inner scope of the outer scope. |
| 280 if (outer_scope_ != NULL) { | 293 if (outer_scope_ != NULL) { |
| 281 outer_scope_->inner_scopes_.Add(this); | 294 outer_scope_->inner_scopes_.Add(this); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 return NULL; | 362 return NULL; |
| 350 } | 363 } |
| 351 | 364 |
| 352 | 365 |
| 353 Variable* Scope::LocalLookup(Handle<String> name) { | 366 Variable* Scope::LocalLookup(Handle<String> name) { |
| 354 Variable* result = variables_.Lookup(name); | 367 Variable* result = variables_.Lookup(name); |
| 355 if (result != NULL || scope_info_.is_null()) { | 368 if (result != NULL || scope_info_.is_null()) { |
| 356 return result; | 369 return result; |
| 357 } | 370 } |
| 358 // If we have a serialized scope info, we might find the variable there. | 371 // If we have a serialized scope info, we might find the variable there. |
| 359 // | |
| 360 // We should never lookup 'arguments' in this scope as it is implicitly | |
| 361 // present in every scope. | |
| 362 ASSERT(*name != *isolate_->factory()->arguments_symbol()); | |
| 363 // There should be no local slot with the given name. | 372 // There should be no local slot with the given name. |
| 364 ASSERT(scope_info_->StackSlotIndex(*name) < 0); | 373 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
| 365 | 374 |
| 366 // Check context slot lookup. | 375 // Check context slot lookup. |
| 367 VariableMode mode; | 376 VariableMode mode; |
| 368 InitializationFlag init_flag; | 377 InitializationFlag init_flag; |
| 369 int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag); | 378 int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag); |
| 370 if (index < 0) { | 379 if (index < 0) { |
| 371 // Check parameters. | 380 // Check parameters. |
| 372 mode = VAR; | 381 mode = VAR; |
| 373 init_flag = kCreatedInitialized; | 382 init_flag = kCreatedInitialized; |
| 374 index = scope_info_->ParameterIndex(*name); | 383 index = scope_info_->ParameterIndex(*name); |
| 375 if (index < 0) { | 384 if (index < 0) return NULL; |
| 376 // Check the function name. | |
| 377 index = scope_info_->FunctionContextSlotIndex(*name, &mode); | |
| 378 if (index < 0) return NULL; | |
| 379 } | |
| 380 } | 385 } |
| 381 | 386 |
| 382 Variable* var = | 387 Variable* var = |
| 383 variables_.Declare(this, | 388 variables_.Declare(this, |
| 384 name, | 389 name, |
| 385 mode, | 390 mode, |
| 386 true, | 391 true, |
| 387 Variable::NORMAL, | 392 Variable::NORMAL, |
| 388 init_flag); | 393 init_flag); |
| 389 var->AllocateTo(Variable::CONTEXT, index); | 394 var->AllocateTo(Variable::CONTEXT, index); |
| 390 return var; | 395 return var; |
| 391 } | 396 } |
| 392 | 397 |
| 393 | 398 |
| 399 Variable* Scope::LookupFunctionVar(Handle<String> name) { | |
| 400 if (function_ != NULL && function_->name().is_identical_to(name)) { | |
| 401 return function_->var(); | |
| 402 } else if (!scope_info_.is_null()) { | |
| 403 // If we are backed by a scope info, try to lookup the variable there. | |
| 404 VariableMode mode; | |
| 405 int index = scope_info_->FunctionContextSlotIndex(*name, &mode); | |
| 406 if (index < 0) return NULL; | |
| 407 Variable* var = DeclareFunctionVar(name, mode); | |
| 408 var->AllocateTo(Variable::CONTEXT, index); | |
| 409 return var; | |
| 410 } else { | |
| 411 return NULL; | |
| 412 } | |
| 413 } | |
| 414 | |
| 415 | |
| 394 Variable* Scope::Lookup(Handle<String> name) { | 416 Variable* Scope::Lookup(Handle<String> name) { |
| 395 for (Scope* scope = this; | 417 for (Scope* scope = this; |
| 396 scope != NULL; | 418 scope != NULL; |
| 397 scope = scope->outer_scope()) { | 419 scope = scope->outer_scope()) { |
| 398 Variable* var = scope->LocalLookup(name); | 420 Variable* var = scope->LocalLookup(name); |
| 399 if (var != NULL) return var; | 421 if (var != NULL) return var; |
| 400 } | 422 } |
| 401 return NULL; | 423 return NULL; |
| 402 } | 424 } |
| 403 | 425 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 552 if (var->IsStackLocal()) { | 574 if (var->IsStackLocal()) { |
| 553 stack_locals->Add(var); | 575 stack_locals->Add(var); |
| 554 } else if (var->IsContextSlot()) { | 576 } else if (var->IsContextSlot()) { |
| 555 context_locals->Add(var); | 577 context_locals->Add(var); |
| 556 } | 578 } |
| 557 } | 579 } |
| 558 } | 580 } |
| 559 } | 581 } |
| 560 | 582 |
| 561 | 583 |
| 562 void Scope::AllocateVariables(Handle<Context> context) { | 584 void Scope::AllocateVariables(Scope* global_scope) { |
| 563 ASSERT(outer_scope_ == NULL); // eval or global scopes only | |
| 564 | |
| 565 // 1) Propagate scope information. | 585 // 1) Propagate scope information. |
| 566 // If we are in an eval scope, we may have other outer scopes about | |
| 567 // which we don't know anything at this point. Thus we must be conservative | |
| 568 // and assume they may invoke eval themselves. Eventually we could capture | |
| 569 // this information in the ScopeInfo and then use it here (by traversing | |
| 570 // the call chain stack, at compile time). | |
| 571 | |
| 572 bool outer_scope_calls_non_strict_eval = false; | 586 bool outer_scope_calls_non_strict_eval = false; |
| 573 if (!is_global_scope()) { | 587 if (outer_scope_ != NULL) { |
| 574 context->ComputeEvalScopeInfo(&outer_scope_calls_non_strict_eval); | 588 outer_scope_calls_non_strict_eval = |
| 589 outer_scope_->outer_scope_calls_non_strict_eval() | | |
| 590 outer_scope_->calls_non_strict_eval(); | |
| 575 } | 591 } |
| 576 PropagateScopeInfo(outer_scope_calls_non_strict_eval); | 592 PropagateScopeInfo(outer_scope_calls_non_strict_eval); |
| 577 | 593 |
| 578 // 2) Resolve variables. | 594 // 2) Resolve variables. |
| 579 Scope* global_scope = NULL; | 595 ResolveVariablesRecursively(global_scope); |
| 580 if (is_global_scope()) global_scope = this; | |
| 581 ResolveVariablesRecursively(global_scope, context); | |
| 582 | 596 |
| 583 // 3) Allocate variables. | 597 // 3) Allocate variables. |
| 584 AllocateVariablesRecursively(); | 598 AllocateVariablesRecursively(); |
| 585 } | 599 } |
| 586 | 600 |
| 587 | 601 |
| 588 bool Scope::AllowsLazyCompilation() const { | 602 bool Scope::AllowsLazyCompilation() const { |
| 589 return !force_eager_compilation_ && HasTrivialOuterContext(); | 603 return !force_eager_compilation_ && HasTrivialOuterContext(); |
| 590 } | 604 } |
| 591 | 605 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 Variable::NORMAL, | 839 Variable::NORMAL, |
| 826 init_flag); | 840 init_flag); |
| 827 // Allocate it by giving it a dynamic lookup. | 841 // Allocate it by giving it a dynamic lookup. |
| 828 var->AllocateTo(Variable::LOOKUP, -1); | 842 var->AllocateTo(Variable::LOOKUP, -1); |
| 829 } | 843 } |
| 830 return var; | 844 return var; |
| 831 } | 845 } |
| 832 | 846 |
| 833 | 847 |
| 834 Variable* Scope::LookupRecursive(Handle<String> name, | 848 Variable* Scope::LookupRecursive(Handle<String> name, |
| 835 Handle<Context> context, | |
| 836 BindingKind* binding_kind) { | 849 BindingKind* binding_kind) { |
| 837 ASSERT(binding_kind != NULL); | 850 ASSERT(binding_kind != NULL); |
| 838 // Try to find the variable in this scope. | 851 // Try to find the variable in this scope. |
| 839 Variable* var = LocalLookup(name); | 852 Variable* var = LocalLookup(name); |
| 840 | 853 |
| 841 // We found a variable and we are done. (Even if there is an 'eval' in | 854 // We found a variable and we are done. (Even if there is an 'eval' in |
| 842 // this scope which introduces the same variable again, the resulting | 855 // this scope which introduces the same variable again, the resulting |
| 843 // variable remains the same.) | 856 // variable remains the same.) |
| 844 if (var != NULL) { | 857 if (var != NULL) { |
| 845 *binding_kind = BOUND; | 858 *binding_kind = BOUND; |
| 846 return var; | 859 return var; |
| 847 } | 860 } |
| 848 | 861 |
| 849 // We did not find a variable locally. Check against the function variable, | 862 // We did not find a variable locally. Check against the function variable, |
| 850 // if any. We can do this for all scopes, since the function variable is | 863 // if any. We can do this for all scopes, since the function variable is |
| 851 // only present - if at all - for function scopes. | 864 // only present - if at all - for function scopes. |
| 852 // | |
| 853 // This lookup corresponds to a lookup in the "intermediate" scope sitting | |
| 854 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | |
| 855 // the name of named function literal is kept in an intermediate scope | |
| 856 // in between this scope and the next outer scope.) | |
| 857 *binding_kind = UNBOUND; | 865 *binding_kind = UNBOUND; |
| 858 if (function_ != NULL && function_->name().is_identical_to(name)) { | 866 var = LookupFunctionVar(name); |
| 859 var = function_->var(); | 867 if (var != NULL) { |
| 860 *binding_kind = BOUND; | 868 *binding_kind = BOUND; |
| 861 } else if (outer_scope_ != NULL) { | 869 } else if (outer_scope_ != NULL) { |
| 862 var = outer_scope_->LookupRecursive(name, context, binding_kind); | 870 var = outer_scope_->LookupRecursive(name, binding_kind); |
| 863 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 871 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
| 864 var->ForceContextAllocation(); | 872 var->ForceContextAllocation(); |
| 865 } | 873 } |
| 874 } else { | |
| 875 ASSERT(is_global_scope()); | |
| 866 } | 876 } |
| 867 | 877 |
| 868 if (is_with_scope()) { | 878 if (is_with_scope()) { |
| 869 // The current scope is a with scope, so the variable binding can not be | 879 // The current scope is a with scope, so the variable binding can not be |
| 870 // statically resolved. However, note that it was necessary to do a lookup | 880 // statically resolved. However, note that it was necessary to do a lookup |
| 871 // in the outer scope anyway, because if a binding exists in an outer scope, | 881 // in the outer scope anyway, because if a binding exists in an outer scope, |
| 872 // the associated variable has to be marked as potentially being accessed | 882 // the associated variable has to be marked as potentially being accessed |
| 873 // from inside of an inner with scope (the property may not be in the 'with' | 883 // from inside of an inner with scope (the property may not be in the 'with' |
| 874 // object). | 884 // object). |
| 875 *binding_kind = DYNAMIC_LOOKUP; | 885 *binding_kind = DYNAMIC_LOOKUP; |
| 876 return NULL; | 886 return NULL; |
| 877 } else if (is_eval_scope()) { | |
| 878 // No local binding was found, no 'with' statements have been encountered | |
| 879 // and the code is executed as part of a call to 'eval'. The calling context | |
| 880 // contains scope information that we can use to determine if the variable | |
| 881 // is global, i.e. the calling context chain does not contain a binding and | |
| 882 // no 'with' contexts. | |
| 883 ASSERT(*binding_kind == UNBOUND); | |
| 884 *binding_kind = context->GlobalIfNotShadowedByEval(name) | |
| 885 ? UNBOUND_EVAL_SHADOWED : DYNAMIC_LOOKUP; | |
| 886 return NULL; | |
| 887 } else if (calls_non_strict_eval()) { | 887 } else if (calls_non_strict_eval()) { |
| 888 // A variable binding may have been found in an outer scope, but the current | 888 // A variable binding may have been found in an outer scope, but the current |
| 889 // scope makes a non-strict 'eval' call, so the found variable may not be | 889 // scope makes a non-strict 'eval' call, so the found variable may not be |
| 890 // the correct one (the 'eval' may introduce a binding with the same name). | 890 // the correct one (the 'eval' may introduce a binding with the same name). |
| 891 // In that case, change the lookup result to reflect this situation. | 891 // In that case, change the lookup result to reflect this situation. |
| 892 if (*binding_kind == BOUND) { | 892 if (*binding_kind == BOUND) { |
| 893 *binding_kind = BOUND_EVAL_SHADOWED; | 893 *binding_kind = BOUND_EVAL_SHADOWED; |
| 894 } else if (*binding_kind == UNBOUND) { | 894 } else if (*binding_kind == UNBOUND) { |
| 895 *binding_kind = UNBOUND_EVAL_SHADOWED; | 895 *binding_kind = UNBOUND_EVAL_SHADOWED; |
| 896 } | 896 } |
| 897 } | 897 } |
| 898 return var; | 898 return var; |
| 899 } | 899 } |
| 900 | 900 |
| 901 | 901 |
| 902 void Scope::ResolveVariable(Scope* global_scope, | 902 void Scope::ResolveVariable(Scope* global_scope, |
| 903 Handle<Context> context, | |
| 904 VariableProxy* proxy) { | 903 VariableProxy* proxy) { |
| 905 ASSERT(global_scope == NULL || global_scope->is_global_scope()); | 904 ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| 906 | 905 |
| 907 // If the proxy is already resolved there's nothing to do | 906 // If the proxy is already resolved there's nothing to do |
| 908 // (functions and consts may be resolved by the parser). | 907 // (functions and consts may be resolved by the parser). |
| 909 if (proxy->var() != NULL) return; | 908 if (proxy->var() != NULL) return; |
| 910 | 909 |
| 911 // Otherwise, try to resolve the variable. | 910 // Otherwise, try to resolve the variable. |
| 912 BindingKind binding_kind; | 911 BindingKind binding_kind; |
| 913 Variable* var = LookupRecursive(proxy->name(), context, &binding_kind); | 912 Variable* var = LookupRecursive(proxy->name(), &binding_kind); |
| 914 switch (binding_kind) { | 913 switch (binding_kind) { |
| 915 case BOUND: | 914 case BOUND: |
| 916 // We found a variable binding. | 915 // We found a variable binding. |
| 917 break; | 916 break; |
| 918 | 917 |
| 919 case BOUND_EVAL_SHADOWED: | 918 case BOUND_EVAL_SHADOWED: |
| 920 // We found a variable variable binding that might be shadowed | 919 // We found a variable variable binding that might be shadowed |
| 921 // by 'eval' introduced variable bindings. | 920 // by 'eval' introduced variable bindings. |
| 922 if (var->is_global()) { | 921 if (var->is_global()) { |
| 923 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); | 922 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 944 // The variable could not be resolved statically. | 943 // The variable could not be resolved statically. |
| 945 var = NonLocal(proxy->name(), DYNAMIC); | 944 var = NonLocal(proxy->name(), DYNAMIC); |
| 946 break; | 945 break; |
| 947 } | 946 } |
| 948 | 947 |
| 949 ASSERT(var != NULL); | 948 ASSERT(var != NULL); |
| 950 proxy->BindTo(var); | 949 proxy->BindTo(var); |
| 951 } | 950 } |
| 952 | 951 |
| 953 | 952 |
| 954 void Scope::ResolveVariablesRecursively(Scope* global_scope, | 953 void Scope::ResolveVariablesRecursively(Scope* global_scope) { |
| 955 Handle<Context> context) { | |
| 956 ASSERT(global_scope == NULL || global_scope->is_global_scope()); | 954 ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| 957 | 955 |
| 958 // Resolve unresolved variables for this scope. | 956 // Resolve unresolved variables for this scope. |
| 959 for (int i = 0; i < unresolved_.length(); i++) { | 957 for (int i = 0; i < unresolved_.length(); i++) { |
| 960 ResolveVariable(global_scope, context, unresolved_[i]); | 958 ResolveVariable(global_scope, unresolved_[i]); |
| 961 } | 959 } |
| 962 | 960 |
| 963 // Resolve unresolved variables for inner scopes. | 961 // Resolve unresolved variables for inner scopes. |
| 964 for (int i = 0; i < inner_scopes_.length(); i++) { | 962 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 965 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context); | 963 inner_scopes_[i]->ResolveVariablesRecursively(global_scope); |
| 966 } | 964 } |
| 967 } | 965 } |
| 968 | 966 |
| 969 | 967 |
| 970 bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) { | 968 bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) { |
| 971 if (outer_scope_calls_non_strict_eval) { | 969 if (outer_scope_calls_non_strict_eval) { |
| 972 outer_scope_calls_non_strict_eval_ = true; | 970 outer_scope_calls_non_strict_eval_ = true; |
| 973 } | 971 } |
| 974 | 972 |
| 975 bool calls_non_strict_eval = | 973 bool calls_non_strict_eval = |
| 976 (scope_calls_eval_ && !is_strict_mode()) || | 974 this->calls_non_strict_eval() || outer_scope_calls_non_strict_eval_; |
| 977 outer_scope_calls_non_strict_eval_; | |
| 978 for (int i = 0; i < inner_scopes_.length(); i++) { | 975 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 979 Scope* inner_scope = inner_scopes_[i]; | 976 Scope* inner_scope = inner_scopes_[i]; |
| 980 if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) { | 977 if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) { |
| 981 inner_scope_calls_eval_ = true; | 978 inner_scope_calls_eval_ = true; |
| 982 } | 979 } |
| 983 if (inner_scope->force_eager_compilation_) { | 980 if (inner_scope->force_eager_compilation_) { |
| 984 force_eager_compilation_ = true; | 981 force_eager_compilation_ = true; |
| 985 } | 982 } |
| 986 } | 983 } |
| 987 | 984 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1180 } | 1177 } |
| 1181 | 1178 |
| 1182 | 1179 |
| 1183 int Scope::ContextLocalCount() const { | 1180 int Scope::ContextLocalCount() const { |
| 1184 if (num_heap_slots() == 0) return 0; | 1181 if (num_heap_slots() == 0) return 0; |
| 1185 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1182 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1186 (function_ != NULL && function_->var()->IsContextSlot() ? 1 : 0); | 1183 (function_ != NULL && function_->var()->IsContextSlot() ? 1 : 0); |
| 1187 } | 1184 } |
| 1188 | 1185 |
| 1189 } } // namespace v8::internal | 1186 } } // namespace v8::internal |
| OLD | NEW |