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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 already_resolved_(false) { | 139 already_resolved_(false) { |
140 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null()); | 140 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null()); |
141 // At some point we might want to provide outer scopes to | 141 // At some point we might want to provide outer scopes to |
142 // eval scopes (by walking the stack and reading the scope info). | 142 // eval scopes (by walking the stack and reading the scope info). |
143 // In that case, the ASSERT below needs to be adjusted. | 143 // In that case, the ASSERT below needs to be adjusted. |
144 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); | 144 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); |
145 ASSERT(!HasIllegalRedeclaration()); | 145 ASSERT(!HasIllegalRedeclaration()); |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info) | 149 Scope::Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_in fo) |
150 : isolate_(Isolate::Current()), | 150 : isolate_(Isolate::Current()), |
151 inner_scopes_(4), | 151 inner_scopes_(4), |
152 variables_(), | 152 variables_(), |
153 temps_(4), | 153 temps_(4), |
154 params_(4), | 154 params_(4), |
155 unresolved_(16), | 155 unresolved_(16), |
156 decls_(4), | 156 decls_(4), |
157 already_resolved_(true) { | 157 already_resolved_(true) { |
158 ASSERT(!scope_info.is_null()); | 158 ASSERT(!scope_info.is_null()); |
159 SetDefaults(FUNCTION_SCOPE, NULL, scope_info); | 159 SetDefaults(type, NULL, scope_info); |
160 if (scope_info->HasHeapAllocatedLocals()) { | 160 if (scope_info->HasHeapAllocatedLocals()) { |
161 num_heap_slots_ = scope_info_->NumberOfContextSlots(); | 161 num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
162 } | 162 } |
163 AddInnerScope(inner_scope); | 163 AddInnerScope(inner_scope); |
164 } | 164 } |
165 | 165 |
166 | 166 |
167 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) | 167 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) |
168 : isolate_(Isolate::Current()), | 168 : isolate_(Isolate::Current()), |
169 inner_scopes_(1), | 169 inner_scopes_(1), |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 if (context->IsWithContext()) { | 225 if (context->IsWithContext()) { |
226 // All the inner scopes are inside a with. | 226 // All the inner scopes are inside a with. |
227 contains_with = true; | 227 contains_with = true; |
228 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 228 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
229 s->scope_inside_with_ = true; | 229 s->scope_inside_with_ = true; |
230 } | 230 } |
231 } else { | 231 } else { |
232 if (context->IsFunctionContext()) { | 232 if (context->IsFunctionContext()) { |
233 SerializedScopeInfo* scope_info = | 233 SerializedScopeInfo* scope_info = |
234 context->closure()->shared()->scope_info(); | 234 context->closure()->shared()->scope_info(); |
235 current_scope = | 235 current_scope = new Scope(current_scope, FUNCTION_SCOPE, |
236 new Scope(current_scope, Handle<SerializedScopeInfo>(scope_info)); | 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)); | |
237 } else { | 242 } else { |
238 ASSERT(context->IsCatchContext()); | 243 ASSERT(context->IsCatchContext()); |
239 String* name = String::cast(context->extension()); | 244 String* name = String::cast(context->extension()); |
240 current_scope = new Scope(current_scope, Handle<String>(name)); | 245 current_scope = new Scope(current_scope, Handle<String>(name)); |
241 } | 246 } |
242 if (contains_with) current_scope->RecordWithStatement(); | 247 if (contains_with) current_scope->RecordWithStatement(); |
243 if (innermost_scope == NULL) innermost_scope = current_scope; | 248 if (innermost_scope == NULL) innermost_scope = current_scope; |
244 } | 249 } |
245 | 250 |
246 // Forget about a with when we move to a context for a different function. | 251 // Forget about a with when we move to a context for a different function. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
287 } | 292 } |
288 | 293 |
289 // Declare convenience variables. | 294 // Declare convenience variables. |
290 // Declare and allocate receiver (even for the global scope, and even | 295 // Declare and allocate receiver (even for the global scope, and even |
291 // if naccesses_ == 0). | 296 // if naccesses_ == 0). |
292 // NOTE: When loading parameters in the global scope, we must take | 297 // NOTE: When loading parameters in the global scope, we must take |
293 // care not to access them as properties of the global object, but | 298 // care not to access them as properties of the global object, but |
294 // instead load them directly from the stack. Currently, the only | 299 // instead load them directly from the stack. Currently, the only |
295 // such parameter is 'this' which is passed on the stack when | 300 // such parameter is 'this' which is passed on the stack when |
296 // invoking scripts | 301 // invoking scripts |
297 if (is_catch_scope()) { | 302 if (is_catch_scope() || is_block_scope()) { |
298 ASSERT(outer_scope() != NULL); | 303 ASSERT(outer_scope() != NULL); |
299 receiver_ = outer_scope()->receiver(); | 304 receiver_ = outer_scope()->receiver(); |
300 } else { | 305 } else { |
306 ASSERT(is_function_scope() || | |
307 is_global_scope() || | |
308 is_eval_scope()); | |
301 Variable* var = | 309 Variable* var = |
302 variables_.Declare(this, | 310 variables_.Declare(this, |
303 isolate_->factory()->this_symbol(), | 311 isolate_->factory()->this_symbol(), |
304 Variable::VAR, | 312 Variable::VAR, |
305 false, | 313 false, |
306 Variable::THIS); | 314 Variable::THIS); |
307 var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1)); | 315 var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1)); |
308 receiver_ = var; | 316 receiver_ = var; |
309 } | 317 } |
310 | 318 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
552 for (Scope* s = this; s != scope; s = s->outer_scope_) { | 560 for (Scope* s = this; s != scope; s = s->outer_scope_) { |
553 ASSERT(s != NULL); // scope must be in the scope chain | 561 ASSERT(s != NULL); // scope must be in the scope chain |
554 if (s->num_heap_slots() > 0) n++; | 562 if (s->num_heap_slots() > 0) n++; |
555 } | 563 } |
556 return n; | 564 return n; |
557 } | 565 } |
558 | 566 |
559 | 567 |
560 Scope* Scope::DeclarationScope() { | 568 Scope* Scope::DeclarationScope() { |
561 Scope* scope = this; | 569 Scope* scope = this; |
562 while (scope->is_catch_scope()) { | 570 while (scope->is_catch_scope() || |
571 scope->is_block_scope()) { | |
563 scope = scope->outer_scope(); | 572 scope = scope->outer_scope(); |
564 } | 573 } |
565 return scope; | 574 return scope; |
566 } | 575 } |
567 | 576 |
568 | 577 |
578 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { | |
579 if (scope_info_.is_null()) { | |
580 scope_info_ = SerializedScopeInfo::Create(this); | |
581 } | |
582 return scope_info_; | |
583 } | |
584 | |
585 | |
569 #ifdef DEBUG | 586 #ifdef DEBUG |
570 static const char* Header(Scope::Type type) { | 587 static const char* Header(Scope::Type type) { |
571 switch (type) { | 588 switch (type) { |
572 case Scope::EVAL_SCOPE: return "eval"; | 589 case Scope::EVAL_SCOPE: return "eval"; |
573 case Scope::FUNCTION_SCOPE: return "function"; | 590 case Scope::FUNCTION_SCOPE: return "function"; |
574 case Scope::GLOBAL_SCOPE: return "global"; | 591 case Scope::GLOBAL_SCOPE: return "global"; |
575 case Scope::CATCH_SCOPE: return "catch"; | 592 case Scope::CATCH_SCOPE: return "catch"; |
593 case Scope::BLOCK_SCOPE: return "block"; | |
576 } | 594 } |
577 UNREACHABLE(); | 595 UNREACHABLE(); |
578 return NULL; | 596 return NULL; |
579 } | 597 } |
580 | 598 |
581 | 599 |
582 static void Indent(int n, const char* str) { | 600 static void Indent(int n, const char* str) { |
583 PrintF("%*s%s", n, "", str); | 601 PrintF("%*s%s", n, "", str); |
584 } | 602 } |
585 | 603 |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 // only present - if at all - for function scopes. | 764 // only present - if at all - for function scopes. |
747 // | 765 // |
748 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 766 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
749 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 767 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
750 // the name of named function literal is kept in an intermediate scope | 768 // the name of named function literal is kept in an intermediate scope |
751 // in between this scope and the next outer scope.) | 769 // in between this scope and the next outer scope.) |
752 if (function_ != NULL && function_->name().is_identical_to(name)) { | 770 if (function_ != NULL && function_->name().is_identical_to(name)) { |
753 var = function_; | 771 var = function_; |
754 | 772 |
755 } else if (outer_scope_ != NULL) { | 773 } else if (outer_scope_ != NULL) { |
756 var = outer_scope_->LookupRecursive(name, true, invalidated_local); | 774 var = outer_scope_->LookupRecursive( |
775 name, | |
776 is_block_scope() || is_catch_scope() ? inner_lookup : true, | |
Kevin Millikin (Chromium)
2011/08/10 11:19:27
This is subtle. I'd probably change all the ident
Steven
2011/08/10 12:21:00
Done.
| |
777 invalidated_local); | |
757 // We may have found a variable in an outer scope. However, if | 778 // We may have found a variable in an outer scope. However, if |
758 // the current scope is inside a 'with', the actual variable may | 779 // the current scope is inside a 'with', the actual variable may |
759 // be a property introduced via the 'with' statement. Then, the | 780 // be a property introduced via the 'with' statement. Then, the |
760 // variable we may have found is just a guess. | 781 // variable we may have found is just a guess. |
761 if (scope_inside_with_) | 782 if (scope_inside_with_) |
762 guess = true; | 783 guess = true; |
763 } | 784 } |
764 | 785 |
765 // If we did not find a variable, we are done. | 786 // If we did not find a variable, we are done. |
766 if (var == NULL) | 787 if (var == NULL) |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 | 940 |
920 bool Scope::MustAllocate(Variable* var) { | 941 bool Scope::MustAllocate(Variable* var) { |
921 // Give var a read/write use if there is a chance it might be accessed | 942 // Give var a read/write use if there is a chance it might be accessed |
922 // via an eval() call. This is only possible if the variable has a | 943 // via an eval() call. This is only possible if the variable has a |
923 // visible name. | 944 // visible name. |
924 if ((var->is_this() || var->name()->length() > 0) && | 945 if ((var->is_this() || var->name()->length() > 0) && |
925 (var->is_accessed_from_inner_scope() || | 946 (var->is_accessed_from_inner_scope() || |
926 scope_calls_eval_ || | 947 scope_calls_eval_ || |
927 inner_scope_calls_eval_ || | 948 inner_scope_calls_eval_ || |
928 scope_contains_with_ || | 949 scope_contains_with_ || |
929 is_catch_scope())) { | 950 is_catch_scope() || |
951 is_block_scope())) { | |
930 var->set_is_used(true); | 952 var->set_is_used(true); |
931 } | 953 } |
932 // Global variables do not need to be allocated. | 954 // Global variables do not need to be allocated. |
933 return !var->is_global() && var->is_used(); | 955 return !var->is_global() && var->is_used(); |
934 } | 956 } |
935 | 957 |
936 | 958 |
937 bool Scope::MustAllocateInContext(Variable* var) { | 959 bool Scope::MustAllocateInContext(Variable* var) { |
938 // If var is accessed from an inner scope, or if there is a possibility | 960 // If var is accessed from an inner scope, or if there is a possibility |
939 // that it might be accessed from the current or an inner scope (through | 961 // that it might be accessed from the current or an inner scope (through |
940 // an eval() call or a runtime with lookup), it must be allocated in the | 962 // an eval() call or a runtime with lookup), it must be allocated in the |
941 // context. | 963 // context. |
942 // | 964 // |
943 // Exceptions: temporary variables are never allocated in a context; | 965 // Exceptions: temporary variables are never allocated in a context; |
944 // catch-bound variables are always allocated in a context. | 966 // catch-bound variables are always allocated in a context. |
945 if (var->mode() == Variable::TEMPORARY) return false; | 967 if (var->mode() == Variable::TEMPORARY) return false; |
946 if (is_catch_scope()) return true; | 968 if (is_catch_scope() || is_block_scope()) return true; |
947 return var->is_accessed_from_inner_scope() || | 969 return var->is_accessed_from_inner_scope() || |
948 scope_calls_eval_ || | 970 scope_calls_eval_ || |
949 inner_scope_calls_eval_ || | 971 inner_scope_calls_eval_ || |
950 scope_contains_with_ || | 972 scope_contains_with_ || |
951 var->is_global(); | 973 var->is_global(); |
952 } | 974 } |
953 | 975 |
954 | 976 |
955 bool Scope::HasArgumentsParameter() { | 977 bool Scope::HasArgumentsParameter() { |
956 for (int i = 0; i < params_.length(); i++) { | 978 for (int i = 0; i < params_.length(); i++) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1103 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1125 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
1104 !must_have_local_context) { | 1126 !must_have_local_context) { |
1105 num_heap_slots_ = 0; | 1127 num_heap_slots_ = 0; |
1106 } | 1128 } |
1107 | 1129 |
1108 // Allocation done. | 1130 // Allocation done. |
1109 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1131 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
1110 } | 1132 } |
1111 | 1133 |
1112 } } // namespace v8::internal | 1134 } } // namespace v8::internal |
OLD | NEW |