Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Side by Side Diff: src/scopes.cc

Issue 7904008: Introduce with scope and rework variable resolution. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Latest version. Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/scopes.h ('k') | src/variables.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 Type type, 149 Type type,
150 Handle<SerializedScopeInfo> scope_info) 150 Handle<SerializedScopeInfo> scope_info)
151 : isolate_(Isolate::Current()), 151 : isolate_(Isolate::Current()),
152 inner_scopes_(4), 152 inner_scopes_(4),
153 variables_(), 153 variables_(),
154 temps_(4), 154 temps_(4),
155 params_(4), 155 params_(4),
156 unresolved_(16), 156 unresolved_(16),
157 decls_(4), 157 decls_(4),
158 already_resolved_(true) { 158 already_resolved_(true) {
159 ASSERT(!scope_info.is_null());
160 SetDefaults(type, NULL, scope_info); 159 SetDefaults(type, NULL, scope_info);
161 if (scope_info->HasHeapAllocatedLocals()) { 160 if (!scope_info.is_null() && scope_info->HasHeapAllocatedLocals()) {
162 num_heap_slots_ = scope_info_->NumberOfContextSlots(); 161 num_heap_slots_ = scope_info_->NumberOfContextSlots();
163 } 162 }
164 AddInnerScope(inner_scope); 163 AddInnerScope(inner_scope);
165 } 164 }
166 165
167 166
168 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) 167 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
169 : isolate_(Isolate::Current()), 168 : isolate_(Isolate::Current()),
170 inner_scopes_(1), 169 inner_scopes_(1),
171 variables_(), 170 variables_(),
(...skipping 23 matching lines...) Expand all
195 dynamics_ = NULL; 194 dynamics_ = NULL;
196 receiver_ = NULL; 195 receiver_ = NULL;
197 function_ = NULL; 196 function_ = NULL;
198 arguments_ = NULL; 197 arguments_ = NULL;
199 illegal_redecl_ = NULL; 198 illegal_redecl_ = NULL;
200 scope_inside_with_ = false; 199 scope_inside_with_ = false;
201 scope_contains_with_ = false; 200 scope_contains_with_ = false;
202 scope_calls_eval_ = false; 201 scope_calls_eval_ = false;
203 // Inherit the strict mode from the parent scope. 202 // Inherit the strict mode from the parent scope.
204 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; 203 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
205 outer_scope_calls_eval_ = false;
206 outer_scope_calls_non_strict_eval_ = false; 204 outer_scope_calls_non_strict_eval_ = false;
207 inner_scope_calls_eval_ = false; 205 inner_scope_calls_eval_ = false;
208 outer_scope_is_eval_scope_ = false;
209 force_eager_compilation_ = false; 206 force_eager_compilation_ = false;
210 num_var_or_const_ = 0; 207 num_var_or_const_ = 0;
211 num_stack_slots_ = 0; 208 num_stack_slots_ = 0;
212 num_heap_slots_ = 0; 209 num_heap_slots_ = 0;
213 scope_info_ = scope_info; 210 scope_info_ = scope_info;
214 } 211 }
215 212
216 213
217 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 214 Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
218 Scope* global_scope) { 215 Scope* global_scope) {
219 // Reconstruct the outer scope chain from a closure's context chain. 216 // Reconstruct the outer scope chain from a closure's context chain.
220 ASSERT(!info->closure().is_null()); 217 ASSERT(!info->closure().is_null());
221 Context* context = info->closure()->context(); 218 Context* context = info->closure()->context();
222 Scope* current_scope = NULL; 219 Scope* current_scope = NULL;
223 Scope* innermost_scope = NULL; 220 Scope* innermost_scope = NULL;
224 bool contains_with = false; 221 bool contains_with = false;
225 while (!context->IsGlobalContext()) { 222 while (!context->IsGlobalContext()) {
226 if (context->IsWithContext()) { 223 if (context->IsWithContext()) {
224 Scope* with_scope = new Scope(current_scope, WITH_SCOPE,
225 Handle<SerializedScopeInfo>::null());
226 current_scope = with_scope;
227 // All the inner scopes are inside a with. 227 // All the inner scopes are inside a with.
228 contains_with = true; 228 contains_with = true;
229 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { 229 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
230 s->scope_inside_with_ = true; 230 s->scope_inside_with_ = true;
231 } 231 }
232 } else if (context->IsFunctionContext()) {
233 SerializedScopeInfo* scope_info =
234 context->closure()->shared()->scope_info();
235 current_scope = new Scope(current_scope, FUNCTION_SCOPE,
236 Handle<SerializedScopeInfo>(scope_info));
237 } else if (context->IsBlockContext()) {
238 SerializedScopeInfo* scope_info =
239 SerializedScopeInfo::cast(context->extension());
240 current_scope = new Scope(current_scope, BLOCK_SCOPE,
241 Handle<SerializedScopeInfo>(scope_info));
232 } else { 242 } else {
233 if (context->IsFunctionContext()) { 243 ASSERT(context->IsCatchContext());
234 SerializedScopeInfo* scope_info = 244 String* name = String::cast(context->extension());
235 context->closure()->shared()->scope_info(); 245 current_scope = new Scope(current_scope, Handle<String>(name));
236 current_scope = new Scope(current_scope, FUNCTION_SCOPE,
237 Handle<SerializedScopeInfo>(scope_info));
238 } else if (context->IsBlockContext()) {
239 SerializedScopeInfo* scope_info =
240 SerializedScopeInfo::cast(context->extension());
241 current_scope = new Scope(current_scope, BLOCK_SCOPE,
242 Handle<SerializedScopeInfo>(scope_info));
243 } else {
244 ASSERT(context->IsCatchContext());
245 String* name = String::cast(context->extension());
246 current_scope = new Scope(current_scope, Handle<String>(name));
247 }
248 if (contains_with) current_scope->RecordWithStatement();
249 if (innermost_scope == NULL) innermost_scope = current_scope;
250 } 246 }
247 if (contains_with) current_scope->RecordWithStatement();
248 if (innermost_scope == NULL) innermost_scope = current_scope;
251 249
252 // Forget about a with when we move to a context for a different function. 250 // Forget about a with when we move to a context for a different function.
253 if (context->previous()->closure() != context->closure()) { 251 if (context->previous()->closure() != context->closure()) {
254 contains_with = false; 252 contains_with = false;
255 } 253 }
256 context = context->previous(); 254 context = context->previous();
257 } 255 }
258 256
259 global_scope->AddInnerScope(current_scope); 257 global_scope->AddInnerScope(current_scope);
260 return (innermost_scope == NULL) ? global_scope : innermost_scope; 258 return (innermost_scope == NULL) ? global_scope : innermost_scope;
(...skipping 13 matching lines...) Expand all
274 : FLAG_print_scopes) { 272 : FLAG_print_scopes) {
275 info->function()->scope()->Print(); 273 info->function()->scope()->Print();
276 } 274 }
277 #endif 275 #endif
278 276
279 info->SetScope(info->function()->scope()); 277 info->SetScope(info->function()->scope());
280 return true; // Can not fail. 278 return true; // Can not fail.
281 } 279 }
282 280
283 281
284 void Scope::Initialize(bool inside_with) { 282 void Scope::Initialize() {
285 ASSERT(!already_resolved()); 283 ASSERT(!already_resolved());
286 284
287 // Add this scope as a new inner scope of the outer scope. 285 // Add this scope as a new inner scope of the outer scope.
288 if (outer_scope_ != NULL) { 286 if (outer_scope_ != NULL) {
289 outer_scope_->inner_scopes_.Add(this); 287 outer_scope_->inner_scopes_.Add(this);
290 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; 288 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
291 } else { 289 } else {
292 scope_inside_with_ = inside_with; 290 scope_inside_with_ = is_with_scope();
293 } 291 }
294 292
295 // Declare convenience variables. 293 // Declare convenience variables.
296 // Declare and allocate receiver (even for the global scope, and even 294 // Declare and allocate receiver (even for the global scope, and even
297 // if naccesses_ == 0). 295 // if naccesses_ == 0).
298 // NOTE: When loading parameters in the global scope, we must take 296 // NOTE: When loading parameters in the global scope, we must take
299 // care not to access them as properties of the global object, but 297 // care not to access them as properties of the global object, but
300 // instead load them directly from the stack. Currently, the only 298 // instead load them directly from the stack. Currently, the only
301 // such parameter is 'this' which is passed on the stack when 299 // such parameter is 'this' which is passed on the stack when
302 // invoking scripts 300 // invoking scripts
303 if (is_catch_scope() || is_block_scope()) { 301 if (is_declaration_scope()) {
304 ASSERT(outer_scope() != NULL);
305 receiver_ = outer_scope()->receiver();
306 } else {
307 ASSERT(is_function_scope() ||
308 is_global_scope() ||
309 is_eval_scope());
310 Variable* var = 302 Variable* var =
311 variables_.Declare(this, 303 variables_.Declare(this,
312 isolate_->factory()->this_symbol(), 304 isolate_->factory()->this_symbol(),
313 Variable::VAR, 305 Variable::VAR,
314 false, 306 false,
315 Variable::THIS); 307 Variable::THIS);
316 var->AllocateTo(Variable::PARAMETER, -1); 308 var->AllocateTo(Variable::PARAMETER, -1);
317 receiver_ = var; 309 receiver_ = var;
310 } else {
311 ASSERT(outer_scope() != NULL);
312 receiver_ = outer_scope()->receiver();
318 } 313 }
319 314
320 if (is_function_scope()) { 315 if (is_function_scope()) {
321 // Declare 'arguments' variable which exists in all functions. 316 // Declare 'arguments' variable which exists in all functions.
322 // Note that it might never be accessed, in which case it won't be 317 // Note that it might never be accessed, in which case it won't be
323 // allocated during variable allocation. 318 // allocated during variable allocation.
324 variables_.Declare(this, 319 variables_.Declare(this,
325 isolate_->factory()->arguments_symbol(), 320 isolate_->factory()->arguments_symbol(),
326 Variable::VAR, 321 Variable::VAR,
327 true, 322 true,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 431
437 432
438 Variable* Scope::DeclareGlobal(Handle<String> name) { 433 Variable* Scope::DeclareGlobal(Handle<String> name) {
439 ASSERT(is_global_scope()); 434 ASSERT(is_global_scope());
440 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, 435 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL,
441 true, 436 true,
442 Variable::NORMAL); 437 Variable::NORMAL);
443 } 438 }
444 439
445 440
446 VariableProxy* Scope::NewUnresolved(Handle<String> name, 441 VariableProxy* Scope::NewUnresolved(Handle<String> name, int position) {
447 bool inside_with,
448 int position) {
449 // Note that we must not share the unresolved variables with 442 // Note that we must not share the unresolved variables with
450 // the same name because they may be removed selectively via 443 // the same name because they may be removed selectively via
451 // RemoveUnresolved(). 444 // RemoveUnresolved().
452 ASSERT(!already_resolved()); 445 ASSERT(!already_resolved());
453 VariableProxy* proxy = new(isolate_->zone()) VariableProxy( 446 VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
454 isolate_, name, false, inside_with, position); 447 isolate_, name, false, position);
455 unresolved_.Add(proxy); 448 unresolved_.Add(proxy);
456 return proxy; 449 return proxy;
457 } 450 }
458 451
459 452
460 void Scope::RemoveUnresolved(VariableProxy* var) { 453 void Scope::RemoveUnresolved(VariableProxy* var) {
461 // Most likely (always?) any variable we want to remove 454 // Most likely (always?) any variable we want to remove
462 // was just added before, so we search backwards. 455 // was just added before, so we search backwards.
463 for (int i = unresolved_.length(); i-- > 0;) { 456 for (int i = unresolved_.length(); i-- > 0;) {
464 if (unresolved_[i] == var) { 457 if (unresolved_[i] == var) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 illegal_redecl_->Accept(visitor); 493 illegal_redecl_->Accept(visitor);
501 } 494 }
502 495
503 496
504 Declaration* Scope::CheckConflictingVarDeclarations() { 497 Declaration* Scope::CheckConflictingVarDeclarations() {
505 int length = decls_.length(); 498 int length = decls_.length();
506 for (int i = 0; i < length; i++) { 499 for (int i = 0; i < length; i++) {
507 Declaration* decl = decls_[i]; 500 Declaration* decl = decls_[i];
508 if (decl->mode() != Variable::VAR) continue; 501 if (decl->mode() != Variable::VAR) continue;
509 Handle<String> name = decl->proxy()->name(); 502 Handle<String> name = decl->proxy()->name();
510 bool cond = true; 503
511 for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) { 504 // Iterate through all scopes until and including the declaration scope.
505 Scope* previous = NULL;
506 Scope* current = decl->scope();
507 do {
512 // There is a conflict if there exists a non-VAR binding. 508 // There is a conflict if there exists a non-VAR binding.
513 Variable* other_var = scope->variables_.Lookup(name); 509 Variable* other_var = current->variables_.Lookup(name);
514 if (other_var != NULL && other_var->mode() != Variable::VAR) { 510 if (other_var != NULL && other_var->mode() != Variable::VAR) {
515 return decl; 511 return decl;
516 } 512 }
517 513 previous = current;
518 // Include declaration scope in the iteration but stop after. 514 current = current->outer_scope_;
519 if (!scope->is_block_scope() && !scope->is_catch_scope()) cond = false; 515 } while (!previous->is_declaration_scope());
520 }
521 } 516 }
522 return NULL; 517 return NULL;
523 } 518 }
524 519
525 520
526 template<class Allocator> 521 template<class Allocator>
527 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { 522 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
528 // Collect variables in this scope. 523 // Collect variables in this scope.
529 // Note that the function_ variable - if present - is not 524 // Note that the function_ variable - if present - is not
530 // collected here but handled separately in ScopeInfo 525 // collected here but handled separately in ScopeInfo
(...skipping 27 matching lines...) Expand all
558 void Scope::AllocateVariables(Handle<Context> context) { 553 void Scope::AllocateVariables(Handle<Context> context) {
559 ASSERT(outer_scope_ == NULL); // eval or global scopes only 554 ASSERT(outer_scope_ == NULL); // eval or global scopes only
560 555
561 // 1) Propagate scope information. 556 // 1) Propagate scope information.
562 // If we are in an eval scope, we may have other outer scopes about 557 // If we are in an eval scope, we may have other outer scopes about
563 // which we don't know anything at this point. Thus we must be conservative 558 // which we don't know anything at this point. Thus we must be conservative
564 // and assume they may invoke eval themselves. Eventually we could capture 559 // and assume they may invoke eval themselves. Eventually we could capture
565 // this information in the ScopeInfo and then use it here (by traversing 560 // this information in the ScopeInfo and then use it here (by traversing
566 // the call chain stack, at compile time). 561 // the call chain stack, at compile time).
567 562
568 bool eval_scope = is_eval_scope();
569 bool outer_scope_calls_eval = false;
570 bool outer_scope_calls_non_strict_eval = false; 563 bool outer_scope_calls_non_strict_eval = false;
571 if (!is_global_scope()) { 564 if (!is_global_scope()) {
572 context->ComputeEvalScopeInfo(&outer_scope_calls_eval, 565 context->ComputeEvalScopeInfo(&outer_scope_calls_non_strict_eval);
573 &outer_scope_calls_non_strict_eval);
574 } 566 }
575 PropagateScopeInfo(outer_scope_calls_eval, 567 PropagateScopeInfo(outer_scope_calls_non_strict_eval);
576 outer_scope_calls_non_strict_eval,
577 eval_scope);
578 568
579 // 2) Resolve variables. 569 // 2) Resolve variables.
580 Scope* global_scope = NULL; 570 Scope* global_scope = NULL;
581 if (is_global_scope()) global_scope = this; 571 if (is_global_scope()) global_scope = this;
582 ResolveVariablesRecursively(global_scope, context); 572 ResolveVariablesRecursively(global_scope, context);
583 573
584 // 3) Allocate variables. 574 // 3) Allocate variables.
585 AllocateVariablesRecursively(); 575 AllocateVariablesRecursively();
586 } 576 }
587 577
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 for (Scope* s = this; s != scope; s = s->outer_scope_) { 610 for (Scope* s = this; s != scope; s = s->outer_scope_) {
621 ASSERT(s != NULL); // scope must be in the scope chain 611 ASSERT(s != NULL); // scope must be in the scope chain
622 if (s->num_heap_slots() > 0) n++; 612 if (s->num_heap_slots() > 0) n++;
623 } 613 }
624 return n; 614 return n;
625 } 615 }
626 616
627 617
628 Scope* Scope::DeclarationScope() { 618 Scope* Scope::DeclarationScope() {
629 Scope* scope = this; 619 Scope* scope = this;
630 while (scope->is_catch_scope() || 620 while (!scope->is_declaration_scope()) {
631 scope->is_block_scope()) {
632 scope = scope->outer_scope(); 621 scope = scope->outer_scope();
633 } 622 }
634 return scope; 623 return scope;
635 } 624 }
636 625
637 626
638 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { 627 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() {
639 if (scope_info_.is_null()) { 628 if (scope_info_.is_null()) {
640 scope_info_ = SerializedScopeInfo::Create(this); 629 scope_info_ = SerializedScopeInfo::Create(this);
641 } 630 }
642 return scope_info_; 631 return scope_info_;
643 } 632 }
644 633
645 634
646 #ifdef DEBUG 635 #ifdef DEBUG
647 static const char* Header(Scope::Type type) { 636 static const char* Header(Scope::Type type) {
648 switch (type) { 637 switch (type) {
649 case Scope::EVAL_SCOPE: return "eval"; 638 case Scope::EVAL_SCOPE: return "eval";
650 case Scope::FUNCTION_SCOPE: return "function"; 639 case Scope::FUNCTION_SCOPE: return "function";
651 case Scope::GLOBAL_SCOPE: return "global"; 640 case Scope::GLOBAL_SCOPE: return "global";
652 case Scope::CATCH_SCOPE: return "catch"; 641 case Scope::CATCH_SCOPE: return "catch";
653 case Scope::BLOCK_SCOPE: return "block"; 642 case Scope::BLOCK_SCOPE: return "block";
643 case Scope::WITH_SCOPE: return "with";
654 } 644 }
655 UNREACHABLE(); 645 UNREACHABLE();
656 return NULL; 646 return NULL;
657 } 647 }
658 648
659 649
660 static void Indent(int n, const char* str) { 650 static void Indent(int n, const char* str) {
661 PrintF("%*s%s", n, "", str); 651 PrintF("%*s%s", n, "", str);
662 } 652 }
663 653
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 } 733 }
744 734
745 // Scope info. 735 // Scope info.
746 if (HasTrivialOuterContext()) { 736 if (HasTrivialOuterContext()) {
747 Indent(n1, "// scope has trivial outer context\n"); 737 Indent(n1, "// scope has trivial outer context\n");
748 } 738 }
749 if (is_strict_mode()) Indent(n1, "// strict mode scope\n"); 739 if (is_strict_mode()) Indent(n1, "// strict mode scope\n");
750 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 740 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
751 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); 741 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
752 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 742 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
753 if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
754 if (outer_scope_calls_non_strict_eval_) { 743 if (outer_scope_calls_non_strict_eval_) {
755 Indent(n1, "// outer scope calls 'eval' in non-strict context\n"); 744 Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
756 } 745 }
757 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 746 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
758 if (outer_scope_is_eval_scope_) {
759 Indent(n1, "// outer scope is 'eval' scope\n");
760 }
761 if (num_stack_slots_ > 0) { Indent(n1, "// "); 747 if (num_stack_slots_ > 0) { Indent(n1, "// ");
762 PrintF("%d stack slots\n", num_stack_slots_); } 748 PrintF("%d stack slots\n", num_stack_slots_); }
763 if (num_heap_slots_ > 0) { Indent(n1, "// "); 749 if (num_heap_slots_ > 0) { Indent(n1, "// ");
764 PrintF("%d heap slots\n", num_heap_slots_); } 750 PrintF("%d heap slots\n", num_heap_slots_); }
765 751
766 // Print locals. 752 // Print locals.
767 Indent(n1, "// function var\n"); 753 Indent(n1, "// function var\n");
768 if (function_ != NULL) { 754 if (function_ != NULL) {
769 PrintVar(n1, function_->var()); 755 PrintVar(n1, function_->var());
770 } 756 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 if (var == NULL) { 790 if (var == NULL) {
805 // Declare a new non-local. 791 // Declare a new non-local.
806 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); 792 var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
807 // Allocate it by giving it a dynamic lookup. 793 // Allocate it by giving it a dynamic lookup.
808 var->AllocateTo(Variable::LOOKUP, -1); 794 var->AllocateTo(Variable::LOOKUP, -1);
809 } 795 }
810 return var; 796 return var;
811 } 797 }
812 798
813 799
814 // Lookup a variable starting with this scope. The result is either
815 // the statically resolved variable belonging to an outer scope, or
816 // NULL. It may be NULL because a) we couldn't find a variable, or b)
817 // because the variable is just a guess (and may be shadowed by
818 // another variable that is introduced dynamically via an 'eval' call
819 // or a 'with' statement).
820 Variable* Scope::LookupRecursive(Handle<String> name, 800 Variable* Scope::LookupRecursive(Handle<String> name,
821 bool from_inner_scope, 801 Handle<Context> context,
822 Variable** invalidated_local) { 802 BindingKind* binding_kind) {
823 // If we find a variable, but the current scope calls 'eval', the found 803 ASSERT(binding_kind != NULL);
824 // variable may not be the correct one (the 'eval' may introduce a
825 // property with the same name). In that case, remember that the variable
826 // found is just a guess.
827 bool guess = scope_calls_eval_;
828
829 // Try to find the variable in this scope. 804 // Try to find the variable in this scope.
830 Variable* var = LocalLookup(name); 805 Variable* var = LocalLookup(name);
831 806
807 // We found a variable and we are done. (Even if there is an 'eval' in
808 // this scope which introduces the same variable again, the resulting
809 // variable remains the same.)
832 if (var != NULL) { 810 if (var != NULL) {
833 // We found a variable. If this is not an inner lookup, we are done. 811 *binding_kind = BOUND;
834 // (Even if there is an 'eval' in this scope which introduces the 812 return var;
835 // same variable again, the resulting variable remains the same.
836 // Note that enclosing 'with' statements are handled at the call site.)
837 if (!from_inner_scope)
838 return var;
839
840 } else {
841 // We did not find a variable locally. Check against the function variable,
842 // if any. We can do this for all scopes, since the function variable is
843 // only present - if at all - for function scopes.
844 //
845 // This lookup corresponds to a lookup in the "intermediate" scope sitting
846 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
847 // the name of named function literal is kept in an intermediate scope
848 // in between this scope and the next outer scope.)
849 if (function_ != NULL && function_->name().is_identical_to(name)) {
850 var = function_->var();
851
852 } else if (outer_scope_ != NULL) {
853 var = outer_scope_->LookupRecursive(name, true, invalidated_local);
854 // We may have found a variable in an outer scope. However, if
855 // the current scope is inside a 'with', the actual variable may
856 // be a property introduced via the 'with' statement. Then, the
857 // variable we may have found is just a guess.
858 if (scope_inside_with_)
859 guess = true;
860 }
861
862 // If we did not find a variable, we are done.
863 if (var == NULL)
864 return NULL;
865 } 813 }
866 814
867 ASSERT(var != NULL); 815 // We did not find a variable locally. Check against the function variable,
868 816 // if any. We can do this for all scopes, since the function variable is
869 // If this is a lookup from an inner scope, mark the variable. 817 // only present - if at all - for function scopes.
870 if (from_inner_scope) { 818 //
871 var->MarkAsAccessedFromInnerScope(); 819 // This lookup corresponds to a lookup in the "intermediate" scope sitting
820 // between this scope and the outer scope. (ECMA-262, 3rd., requires that
821 // the name of named function literal is kept in an intermediate scope
822 // in between this scope and the next outer scope.)
823 *binding_kind = UNBOUND;
824 if (function_ != NULL && function_->name().is_identical_to(name)) {
825 var = function_->var();
826 *binding_kind = BOUND;
827 } else if (outer_scope_ != NULL) {
828 var = outer_scope_->LookupRecursive(name, context, binding_kind);
829 if (*binding_kind == BOUND) var->MarkAsAccessedFromInnerScope();
872 } 830 }
873 831
874 // If the variable we have found is just a guess, invalidate the 832 if (is_with_scope()) {
875 // result. If the found variable is local, record that fact so we 833 // The current scope is a with scope, so the variable binding can not be
876 // can generate fast code to get it if it is not shadowed by eval. 834 // statically resolved. However, note that it was necessary to do a lookup
877 if (guess) { 835 // in the outer scope anyway, because if a binding exists in an outer scope,
878 if (!var->is_global()) *invalidated_local = var; 836 // the associated variable has to be marked as potentially being accessed
879 var = NULL; 837 // from inside of an inner with scope (the property may not be in the 'with'
838 // object).
839 *binding_kind = DYNAMIC_LOOKUP;
840 return NULL;
841 } else if (is_eval_scope()) {
842 // No local binding was found, no 'with' statements have been encountered
843 // and the code is executed as part of a call to 'eval'. The calling context
844 // contains scope information that we can use to determine if the variable
845 // is global, i.e. the calling context chain does not contain a binding and
846 // no 'with' contexts.
847 ASSERT(*binding_kind == UNBOUND);
848 *binding_kind = context->GlobalIfNotShadowedByEval(name)
849 ? UNBOUND_EVAL_SHADOWED : DYNAMIC_LOOKUP;
850 return NULL;
851 } else if (calls_non_strict_eval()) {
852 // A variable binding may have been found in an outer scope, but the current
853 // scope makes a non-strict 'eval' call, so the found variable may not be
854 // the correct one (the 'eval' may introduce a binding with the same name).
855 // In that case, change the lookup result to reflect this situation.
856 if (*binding_kind == BOUND) {
857 *binding_kind = BOUND_EVAL_SHADOWED;
858 } else if (*binding_kind == UNBOUND) {
859 *binding_kind = UNBOUND_EVAL_SHADOWED;
860 }
880 } 861 }
881
882 return var; 862 return var;
883 } 863 }
884 864
885 865
886 void Scope::ResolveVariable(Scope* global_scope, 866 void Scope::ResolveVariable(Scope* global_scope,
887 Handle<Context> context, 867 Handle<Context> context,
888 VariableProxy* proxy) { 868 VariableProxy* proxy) {
889 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 869 ASSERT(global_scope == NULL || global_scope->is_global_scope());
890 870
891 // If the proxy is already resolved there's nothing to do 871 // If the proxy is already resolved there's nothing to do
892 // (functions and consts may be resolved by the parser). 872 // (functions and consts may be resolved by the parser).
893 if (proxy->var() != NULL) return; 873 if (proxy->var() != NULL) return;
894 874
895 // Otherwise, try to resolve the variable. 875 // Otherwise, try to resolve the variable.
896 Variable* invalidated_local = NULL; 876 BindingKind binding_kind;
897 Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local); 877 Variable* var = LookupRecursive(proxy->name(), context, &binding_kind);
878 switch (binding_kind) {
879 case BOUND:
880 // We found a variable binding.
881 break;
898 882
899 if (proxy->inside_with()) { 883 case BOUND_EVAL_SHADOWED:
900 // If we are inside a local 'with' statement, all bets are off 884 // We found a variable variable binding that might be shadowed
901 // and we cannot resolve the proxy to a local variable even if 885 // by 'eval' introduced variable bindings.
902 // we found an outer matching variable. 886 if (var->is_global()) {
903 // Note that we must do a lookup anyway, because if we find one, 887 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
904 // we must mark that variable as potentially accessed from this 888 } else {
905 // inner scope (the property may not be in the 'with' object). 889 Variable* invalidated = var;
906 var = NonLocal(proxy->name(), Variable::DYNAMIC); 890 var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
891 var->set_local_if_not_shadowed(invalidated);
892 }
893 break;
907 894
908 } else { 895 case UNBOUND:
909 // We are not inside a local 'with' statement. 896 // No binding has been found. Declare a variable in global scope.
897 ASSERT(global_scope != NULL);
898 var = global_scope->DeclareGlobal(proxy->name());
899 break;
910 900
911 if (var == NULL) { 901 case UNBOUND_EVAL_SHADOWED:
912 // We did not find the variable. We have a global variable 902 // No binding has been found. But some scope makes a
913 // if we are in the global scope (we know already that we 903 // non-strict 'eval' call.
914 // are outside a 'with' statement) or if there is no way 904 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
915 // that the variable might be introduced dynamically (through 905 break;
916 // a local or outer eval() call, or an outer 'with' statement),
917 // or we don't know about the outer scope (because we are
918 // in an eval scope).
919 if (is_global_scope() ||
920 !(scope_inside_with_ || outer_scope_is_eval_scope_ ||
921 scope_calls_eval_ || outer_scope_calls_eval_)) {
922 // We must have a global variable.
923 ASSERT(global_scope != NULL);
924 var = global_scope->DeclareGlobal(proxy->name());
925 906
926 } else if (scope_inside_with_) { 907 case DYNAMIC_LOOKUP:
927 // If we are inside a with statement we give up and look up 908 // The variable could not be resolved statically.
928 // the variable at runtime. 909 var = NonLocal(proxy->name(), Variable::DYNAMIC);
929 var = NonLocal(proxy->name(), Variable::DYNAMIC); 910 break;
930
931 } else if (invalidated_local != NULL) {
932 // No with statements are involved and we found a local
933 // variable that might be shadowed by eval introduced
934 // variables.
935 var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
936 var->set_local_if_not_shadowed(invalidated_local);
937
938 } else if (outer_scope_is_eval_scope_) {
939 // No with statements and we did not find a local and the code
940 // is executed with a call to eval. The context contains
941 // scope information that we can use to determine if the
942 // variable is global if it is not shadowed by eval-introduced
943 // variables.
944 if (context->GlobalIfNotShadowedByEval(proxy->name())) {
945 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
946
947 } else {
948 var = NonLocal(proxy->name(), Variable::DYNAMIC);
949 }
950
951 } else {
952 // No with statements and we did not find a local and the code
953 // is not executed with a call to eval. We know that this
954 // variable is global unless it is shadowed by eval-introduced
955 // variables.
956 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
957 }
958 }
959 } 911 }
960 912
913 ASSERT(var != NULL);
961 proxy->BindTo(var); 914 proxy->BindTo(var);
962 } 915 }
963 916
964 917
965 void Scope::ResolveVariablesRecursively(Scope* global_scope, 918 void Scope::ResolveVariablesRecursively(Scope* global_scope,
966 Handle<Context> context) { 919 Handle<Context> context) {
967 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 920 ASSERT(global_scope == NULL || global_scope->is_global_scope());
968 921
969 // Resolve unresolved variables for this scope. 922 // Resolve unresolved variables for this scope.
970 for (int i = 0; i < unresolved_.length(); i++) { 923 for (int i = 0; i < unresolved_.length(); i++) {
971 ResolveVariable(global_scope, context, unresolved_[i]); 924 ResolveVariable(global_scope, context, unresolved_[i]);
972 } 925 }
973 926
974 // Resolve unresolved variables for inner scopes. 927 // Resolve unresolved variables for inner scopes.
975 for (int i = 0; i < inner_scopes_.length(); i++) { 928 for (int i = 0; i < inner_scopes_.length(); i++) {
976 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context); 929 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context);
977 } 930 }
978 } 931 }
979 932
980 933
981 bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval, 934 bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
982 bool outer_scope_calls_non_strict_eval,
983 bool outer_scope_is_eval_scope) {
984 if (outer_scope_calls_eval) {
985 outer_scope_calls_eval_ = true;
986 }
987
988 if (outer_scope_calls_non_strict_eval) { 935 if (outer_scope_calls_non_strict_eval) {
989 outer_scope_calls_non_strict_eval_ = true; 936 outer_scope_calls_non_strict_eval_ = true;
990 } 937 }
991 938
992 if (outer_scope_is_eval_scope) {
993 outer_scope_is_eval_scope_ = true;
994 }
995
996 bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
997 bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
998 bool calls_non_strict_eval = 939 bool calls_non_strict_eval =
999 (scope_calls_eval_ && !is_strict_mode()) || 940 (scope_calls_eval_ && !is_strict_mode()) ||
1000 outer_scope_calls_non_strict_eval_; 941 outer_scope_calls_non_strict_eval_;
1001 for (int i = 0; i < inner_scopes_.length(); i++) { 942 for (int i = 0; i < inner_scopes_.length(); i++) {
1002 Scope* inner_scope = inner_scopes_[i]; 943 Scope* inner_scope = inner_scopes_[i];
1003 if (inner_scope->PropagateScopeInfo(calls_eval, 944 if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
1004 calls_non_strict_eval,
1005 is_eval)) {
1006 inner_scope_calls_eval_ = true; 945 inner_scope_calls_eval_ = true;
1007 } 946 }
1008 if (inner_scope->force_eager_compilation_) { 947 if (inner_scope->force_eager_compilation_) {
1009 force_eager_compilation_ = true; 948 force_eager_compilation_ = true;
1010 } 949 }
1011 } 950 }
1012 951
1013 return scope_calls_eval_ || inner_scope_calls_eval_; 952 return scope_calls_eval_ || inner_scope_calls_eval_;
1014 } 953 }
1015 954
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1138 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1200 !must_have_local_context) { 1139 !must_have_local_context) {
1201 num_heap_slots_ = 0; 1140 num_heap_slots_ = 0;
1202 } 1141 }
1203 1142
1204 // Allocation done. 1143 // Allocation done.
1205 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1144 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1206 } 1145 }
1207 1146
1208 } } // namespace v8::internal 1147 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698