OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/scopes.h" | 5 #include "src/scopes.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/parser.h" | 10 #include "src/parser.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 module_var_ = NULL; | 182 module_var_ = NULL; |
183 has_simple_parameters_ = true; | 183 has_simple_parameters_ = true; |
184 rest_parameter_ = NULL; | 184 rest_parameter_ = NULL; |
185 rest_index_ = -1; | 185 rest_index_ = -1; |
186 scope_info_ = scope_info; | 186 scope_info_ = scope_info; |
187 start_position_ = RelocInfo::kNoPosition; | 187 start_position_ = RelocInfo::kNoPosition; |
188 end_position_ = RelocInfo::kNoPosition; | 188 end_position_ = RelocInfo::kNoPosition; |
189 if (!scope_info.is_null()) { | 189 if (!scope_info.is_null()) { |
190 scope_calls_eval_ = scope_info->CallsEval(); | 190 scope_calls_eval_ = scope_info->CallsEval(); |
191 language_mode_ = scope_info->language_mode(); | 191 language_mode_ = scope_info->language_mode(); |
| 192 is_declaration_scope_ = scope_info->is_declaration_scope(); |
192 function_kind_ = scope_info->function_kind(); | 193 function_kind_ = scope_info->function_kind(); |
193 } | 194 } |
194 } | 195 } |
195 | 196 |
196 | 197 |
197 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 198 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
198 Context* context, Scope* script_scope) { | 199 Context* context, Scope* script_scope) { |
199 // Reconstruct the outer scope chain from a closure's context chain. | 200 // Reconstruct the outer scope chain from a closure's context chain. |
200 Scope* current_scope = NULL; | 201 Scope* current_scope = NULL; |
201 Scope* innermost_scope = NULL; | 202 Scope* innermost_scope = NULL; |
202 bool contains_with = false; | 203 bool contains_with = false; |
203 while (!context->IsNativeContext()) { | 204 while (!context->IsNativeContext()) { |
204 if (context->IsWithContext()) { | 205 if (context->IsWithContext()) { |
205 Scope* with_scope = new (zone) | 206 Scope* with_scope = new (zone) |
206 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), | 207 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), |
207 script_scope->ast_value_factory_); | 208 script_scope->ast_value_factory_); |
208 current_scope = with_scope; | 209 current_scope = with_scope; |
209 // All the inner scopes are inside a with. | 210 // All the inner scopes are inside a with. |
210 contains_with = true; | 211 contains_with = true; |
211 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 212 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
212 s->scope_inside_with_ = true; | 213 s->scope_inside_with_ = true; |
213 } | 214 } |
214 } else if (context->IsScriptContext()) { | 215 } else if (context->IsScriptContext()) { |
215 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); | 216 ScopeInfo* scope_info = context->scope_info(); |
216 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, | 217 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, |
217 Handle<ScopeInfo>(scope_info), | 218 Handle<ScopeInfo>(scope_info), |
218 script_scope->ast_value_factory_); | 219 script_scope->ast_value_factory_); |
219 } else if (context->IsModuleContext()) { | 220 } else if (context->IsModuleContext()) { |
220 ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); | 221 ScopeInfo* scope_info = context->module()->scope_info(); |
221 current_scope = new (zone) Scope(zone, current_scope, MODULE_SCOPE, | 222 current_scope = new (zone) Scope(zone, current_scope, MODULE_SCOPE, |
222 Handle<ScopeInfo>(scope_info), | 223 Handle<ScopeInfo>(scope_info), |
223 script_scope->ast_value_factory_); | 224 script_scope->ast_value_factory_); |
224 } else if (context->IsFunctionContext()) { | 225 } else if (context->IsFunctionContext()) { |
225 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); | 226 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
226 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE, | 227 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE, |
227 Handle<ScopeInfo>(scope_info), | 228 Handle<ScopeInfo>(scope_info), |
228 script_scope->ast_value_factory_); | 229 script_scope->ast_value_factory_); |
229 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; | 230 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; |
230 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; | 231 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; |
231 } else if (context->IsBlockContext()) { | 232 } else if (context->IsBlockContext()) { |
232 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); | 233 ScopeInfo* scope_info = context->scope_info(); |
233 current_scope = new (zone) | 234 current_scope = new (zone) |
234 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), | 235 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), |
235 script_scope->ast_value_factory_); | 236 script_scope->ast_value_factory_); |
236 } else { | 237 } else { |
237 DCHECK(context->IsCatchContext()); | 238 DCHECK(context->IsCatchContext()); |
238 String* name = String::cast(context->extension()); | 239 String* name = context->catch_name(); |
239 current_scope = new (zone) Scope( | 240 current_scope = new (zone) Scope( |
240 zone, current_scope, | 241 zone, current_scope, |
241 script_scope->ast_value_factory_->GetString(Handle<String>(name)), | 242 script_scope->ast_value_factory_->GetString(Handle<String>(name)), |
242 script_scope->ast_value_factory_); | 243 script_scope->ast_value_factory_); |
243 } | 244 } |
244 if (contains_with) current_scope->RecordWithStatement(); | 245 if (contains_with) current_scope->RecordWithStatement(); |
245 if (innermost_scope == NULL) innermost_scope = current_scope; | 246 if (innermost_scope == NULL) innermost_scope = current_scope; |
246 | 247 |
247 // Forget about a with when we move to a context for a different function. | 248 // Forget about a with when we move to a context for a different function. |
248 if (context->previous()->closure() != context->closure()) { | 249 if (context->previous()->closure() != context->closure()) { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 } | 338 } |
338 } | 339 } |
339 } | 340 } |
340 | 341 |
341 | 342 |
342 Scope* Scope::FinalizeBlockScope() { | 343 Scope* Scope::FinalizeBlockScope() { |
343 DCHECK(is_block_scope()); | 344 DCHECK(is_block_scope()); |
344 DCHECK(temps_.is_empty()); | 345 DCHECK(temps_.is_empty()); |
345 DCHECK(params_.is_empty()); | 346 DCHECK(params_.is_empty()); |
346 | 347 |
347 if (num_var_or_const() > 0) return this; | 348 if (num_var_or_const() > 0 || |
| 349 (is_declaration_scope() && calls_sloppy_eval())) { |
| 350 return this; |
| 351 } |
348 | 352 |
349 // Remove this scope from outer scope. | 353 // Remove this scope from outer scope. |
350 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { | 354 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { |
351 if (outer_scope_->inner_scopes_[i] == this) { | 355 if (outer_scope_->inner_scopes_[i] == this) { |
352 outer_scope_->inner_scopes_.Remove(i); | 356 outer_scope_->inner_scopes_.Remove(i); |
353 break; | 357 break; |
354 } | 358 } |
355 } | 359 } |
356 | 360 |
357 // Reparent inner scopes. | 361 // Reparent inner scopes. |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) { | 808 while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) { |
805 top = top->outer_scope(); | 809 top = top->outer_scope(); |
806 } | 810 } |
807 | 811 |
808 top->pending_error_handler_.ReportMessageAt(start_position, end_position, | 812 top->pending_error_handler_.ReportMessageAt(start_position, end_position, |
809 message, arg, kReferenceError); | 813 message, arg, kReferenceError); |
810 } | 814 } |
811 | 815 |
812 | 816 |
813 #ifdef DEBUG | 817 #ifdef DEBUG |
814 static const char* Header(ScopeType scope_type) { | 818 static const char* Header(ScopeType scope_type, bool is_declaration_scope) { |
815 switch (scope_type) { | 819 switch (scope_type) { |
816 case EVAL_SCOPE: return "eval"; | 820 case EVAL_SCOPE: return "eval"; |
817 case FUNCTION_SCOPE: return "function"; | 821 case FUNCTION_SCOPE: return "function"; |
818 case MODULE_SCOPE: return "module"; | 822 case MODULE_SCOPE: return "module"; |
819 case SCRIPT_SCOPE: return "global"; | 823 case SCRIPT_SCOPE: return "global"; |
820 case CATCH_SCOPE: return "catch"; | 824 case CATCH_SCOPE: return "catch"; |
821 case BLOCK_SCOPE: return "block"; | 825 case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block"; |
822 case WITH_SCOPE: return "with"; | 826 case WITH_SCOPE: return "with"; |
823 case ARROW_SCOPE: return "arrow"; | 827 case ARROW_SCOPE: return "arrow"; |
824 } | 828 } |
825 UNREACHABLE(); | 829 UNREACHABLE(); |
826 return NULL; | 830 return NULL; |
827 } | 831 } |
828 | 832 |
829 | 833 |
830 static void Indent(int n, const char* str) { | 834 static void Indent(int n, const char* str) { |
831 PrintF("%*s%s", n, "", str); | 835 PrintF("%*s%s", n, "", str); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 } | 899 } |
896 } | 900 } |
897 } | 901 } |
898 | 902 |
899 | 903 |
900 void Scope::Print(int n) { | 904 void Scope::Print(int n) { |
901 int n0 = (n > 0 ? n : 0); | 905 int n0 = (n > 0 ? n : 0); |
902 int n1 = n0 + 2; // indentation | 906 int n1 = n0 + 2; // indentation |
903 | 907 |
904 // Print header. | 908 // Print header. |
905 Indent(n0, Header(scope_type_)); | 909 Indent(n0, Header(scope_type_, is_declaration_scope())); |
906 if (!scope_name_->IsEmpty()) { | 910 if (!scope_name_->IsEmpty()) { |
907 PrintF(" "); | 911 PrintF(" "); |
908 PrintName(scope_name_); | 912 PrintName(scope_name_); |
909 } | 913 } |
910 | 914 |
911 // Print parameters, if any. | 915 // Print parameters, if any. |
912 if (is_function_scope()) { | 916 if (is_function_scope()) { |
913 PrintF(" ("); | 917 PrintF(" ("); |
914 for (int i = 0; i < params_.length(); i++) { | 918 for (int i = 0; i < params_.length(); i++) { |
915 if (i > 0) PrintF(", "); | 919 if (i > 0) PrintF(", "); |
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 // Allocate variables for this scope. | 1564 // Allocate variables for this scope. |
1561 // Parameters must be allocated first, if any. | 1565 // Parameters must be allocated first, if any. |
1562 if (is_function_scope()) AllocateParameterLocals(isolate); | 1566 if (is_function_scope()) AllocateParameterLocals(isolate); |
1563 if (has_this_declaration()) AllocateReceiver(); | 1567 if (has_this_declaration()) AllocateReceiver(); |
1564 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); | 1568 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); |
1565 | 1569 |
1566 // Force allocation of a context for this scope if necessary. For a 'with' | 1570 // Force allocation of a context for this scope if necessary. For a 'with' |
1567 // scope and for a function scope that makes an 'eval' call we need a context, | 1571 // scope and for a function scope that makes an 'eval' call we need a context, |
1568 // even if no local variables were statically allocated in the scope. | 1572 // even if no local variables were statically allocated in the scope. |
1569 // Likewise for modules. | 1573 // Likewise for modules. |
1570 bool must_have_context = is_with_scope() || is_module_scope() || | 1574 bool must_have_context = |
1571 (is_function_scope() && calls_sloppy_eval()); | 1575 is_with_scope() || is_module_scope() || |
| 1576 (is_function_scope() && calls_sloppy_eval()) || |
| 1577 (is_block_scope() && is_declaration_scope() && calls_sloppy_eval()); |
1572 | 1578 |
1573 // If we didn't allocate any locals in the local context, then we only | 1579 // If we didn't allocate any locals in the local context, then we only |
1574 // need the minimal number of slots if we must have a context. | 1580 // need the minimal number of slots if we must have a context. |
1575 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { | 1581 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { |
1576 num_heap_slots_ = 0; | 1582 num_heap_slots_ = 0; |
1577 } | 1583 } |
1578 | 1584 |
1579 // Allocation done. | 1585 // Allocation done. |
1580 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1586 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
1581 } | 1587 } |
(...skipping 28 matching lines...) Expand all Loading... |
1610 function_ != NULL && function_->proxy()->var()->IsContextSlot(); | 1616 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
1611 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1617 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1612 (is_function_var_in_context ? 1 : 0); | 1618 (is_function_var_in_context ? 1 : 0); |
1613 } | 1619 } |
1614 | 1620 |
1615 | 1621 |
1616 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1622 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1617 | 1623 |
1618 } // namespace internal | 1624 } // namespace internal |
1619 } // namespace v8 | 1625 } // namespace v8 |
OLD | NEW |