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/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 if (context->IsDebugEvaluateContext()) { | 279 if (context->IsDebugEvaluateContext()) { |
280 outer_scope->set_is_debug_evaluate_scope(); | 280 outer_scope->set_is_debug_evaluate_scope(); |
281 } | 281 } |
282 } else if (context->IsScriptContext()) { | 282 } else if (context->IsScriptContext()) { |
283 // If we reach a script context, it's the outermost context with scope | 283 // If we reach a script context, it's the outermost context with scope |
284 // info. The next context will be the native context. Install the scope | 284 // info. The next context will be the native context. Install the scope |
285 // info of this script context onto the existing script scope to avoid | 285 // info of this script context onto the existing script scope to avoid |
286 // nesting script scopes. | 286 // nesting script scopes. |
287 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 287 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
288 script_scope->SetScriptScopeInfo(scope_info); | 288 script_scope->SetScriptScopeInfo(scope_info); |
289 script_scope->DeserializeScopeInfo(isolate, ast_value_factory); | |
290 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | |
291 script_scope->scope_info_ = Handle<ScopeInfo>::null(); | |
292 } | |
293 DCHECK(context->previous()->IsNativeContext()); | 289 DCHECK(context->previous()->IsNativeContext()); |
294 break; | 290 break; |
295 } else if (context->IsFunctionContext()) { | 291 } else if (context->IsFunctionContext()) { |
296 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), | 292 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), |
297 isolate); | 293 isolate); |
298 // TODO(neis): For an eval scope, we currently create an ordinary function | 294 // TODO(neis): For an eval scope, we currently create an ordinary function |
299 // context. This is wrong and needs to be fixed. | 295 // context. This is wrong and needs to be fixed. |
300 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 296 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
301 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 297 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
302 scope_info->scope_type() == EVAL_SCOPE); | 298 scope_info->scope_type() == EVAL_SCOPE); |
(...skipping 15 matching lines...) Expand all Loading... |
318 } else { | 314 } else { |
319 DCHECK(context->IsCatchContext()); | 315 DCHECK(context->IsCatchContext()); |
320 String* name = context->catch_name(); | 316 String* name = context->catch_name(); |
321 outer_scope = new (zone) | 317 outer_scope = new (zone) |
322 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); | 318 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); |
323 } | 319 } |
324 if (current_scope != nullptr) { | 320 if (current_scope != nullptr) { |
325 outer_scope->AddInnerScope(current_scope); | 321 outer_scope->AddInnerScope(current_scope); |
326 } | 322 } |
327 current_scope = outer_scope; | 323 current_scope = outer_scope; |
328 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | |
329 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | 324 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
330 current_scope->scope_info_ = Handle<ScopeInfo>::null(); | 325 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
331 } | 326 } |
332 if (innermost_scope == nullptr) innermost_scope = current_scope; | 327 if (innermost_scope == nullptr) innermost_scope = current_scope; |
333 context = context->previous(); | 328 context = context->previous(); |
334 } | 329 } |
335 | 330 |
336 if (innermost_scope == nullptr) return script_scope; | 331 if (innermost_scope == nullptr) return script_scope; |
337 script_scope->AddInnerScope(current_scope); | 332 script_scope->AddInnerScope(current_scope); |
338 script_scope->PropagateScopeInfo(); | 333 script_scope->PropagateScopeInfo(); |
339 return innermost_scope; | 334 return innermost_scope; |
340 } | 335 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 Handle<String> name_handle(scope_info_->FunctionName(), isolate); | 391 Handle<String> name_handle(scope_info_->FunctionName(), isolate); |
397 const AstRawString* name = ast_value_factory->GetString(name_handle); | 392 const AstRawString* name = ast_value_factory->GetString(name_handle); |
398 VariableMode mode; | 393 VariableMode mode; |
399 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); | 394 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); |
400 if (index >= 0) { | 395 if (index >= 0) { |
401 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); | 396 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); |
402 DCHECK_EQ(mode, result->mode()); | 397 DCHECK_EQ(mode, result->mode()); |
403 result->AllocateTo(VariableLocation::CONTEXT, index); | 398 result->AllocateTo(VariableLocation::CONTEXT, index); |
404 } | 399 } |
405 } | 400 } |
| 401 |
| 402 scope_info_ = Handle<ScopeInfo>::null(); |
406 } | 403 } |
407 | 404 |
408 DeclarationScope* Scope::AsDeclarationScope() { | 405 DeclarationScope* Scope::AsDeclarationScope() { |
409 DCHECK(is_declaration_scope()); | 406 DCHECK(is_declaration_scope()); |
410 return static_cast<DeclarationScope*>(this); | 407 return static_cast<DeclarationScope*>(this); |
411 } | 408 } |
412 | 409 |
413 const DeclarationScope* Scope::AsDeclarationScope() const { | 410 const DeclarationScope* Scope::AsDeclarationScope() const { |
414 DCHECK(is_declaration_scope()); | 411 DCHECK(is_declaration_scope()); |
415 return static_cast<const DeclarationScope*>(this); | 412 return static_cast<const DeclarationScope*>(this); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 } | 602 } |
606 | 603 |
607 | 604 |
608 void Scope::PropagateUsageFlagsToScope(Scope* other) { | 605 void Scope::PropagateUsageFlagsToScope(Scope* other) { |
609 DCHECK_NOT_NULL(other); | 606 DCHECK_NOT_NULL(other); |
610 DCHECK(!already_resolved_); | 607 DCHECK(!already_resolved_); |
611 DCHECK(!other->already_resolved_); | 608 DCHECK(!other->already_resolved_); |
612 if (calls_eval()) other->RecordEvalCall(); | 609 if (calls_eval()) other->RecordEvalCall(); |
613 } | 610 } |
614 | 611 |
| 612 Variable* Scope::LookupInScopeInfo(const AstRawString* name) { |
| 613 Handle<String> name_handle = name->string(); |
| 614 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
| 615 // heap-independent mode, and all strings must be internalized immediately. So |
| 616 // it's ok to get the Handle<String> here. |
| 617 // If we have a serialized scope info, we might find the variable there. |
| 618 // There should be no local slot with the given name. |
| 619 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0); |
| 620 |
| 621 VariableMode mode; |
| 622 InitializationFlag init_flag; |
| 623 MaybeAssignedFlag maybe_assigned_flag; |
| 624 |
| 625 VariableLocation location = VariableLocation::CONTEXT; |
| 626 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, |
| 627 &init_flag, &maybe_assigned_flag); |
| 628 if (index < 0) { |
| 629 location = VariableLocation::GLOBAL; |
| 630 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode, |
| 631 &init_flag, &maybe_assigned_flag); |
| 632 DCHECK(index < 0 || (is_script_scope() && mode == VAR)); |
| 633 } |
| 634 if (index < 0) { |
| 635 location = VariableLocation::LOOKUP; |
| 636 index = scope_info_->ParameterIndex(*name_handle); |
| 637 if (index >= 0) { |
| 638 mode = DYNAMIC; |
| 639 init_flag = kCreatedInitialized; |
| 640 // Be conservative and flag parameters as maybe assigned. Better |
| 641 // information would require ScopeInfo to serialize the maybe_assigned bit |
| 642 // also for parameters. |
| 643 maybe_assigned_flag = kMaybeAssigned; |
| 644 } |
| 645 } |
| 646 if (index < 0 && scope_type() == MODULE_SCOPE) { |
| 647 location = VariableLocation::MODULE; |
| 648 index = -1; // TODO(neis): Find module variables in scope info. |
| 649 } |
| 650 if (index < 0) return nullptr; // Nowhere found. |
| 651 |
| 652 Variable::Kind kind = Variable::NORMAL; |
| 653 if (location == VariableLocation::CONTEXT && |
| 654 index == scope_info_->ReceiverContextSlotIndex()) { |
| 655 kind = Variable::THIS; |
| 656 } |
| 657 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and |
| 658 // ARGUMENTS bindings as their corresponding Variable::Kind. |
| 659 |
| 660 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, |
| 661 maybe_assigned_flag); |
| 662 var->AllocateTo(location, index); |
| 663 return var; |
| 664 } |
| 665 |
615 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { | 666 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { |
616 if (function_ != nullptr && function_->raw_name() == name) return function_; | 667 if (function_ != nullptr && function_->raw_name() == name) { |
617 return nullptr; | 668 return function_; |
| 669 } else if (!scope_info_.is_null()) { |
| 670 // If we are backed by a scope info, try to lookup the variable there. |
| 671 VariableMode mode; |
| 672 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
| 673 if (index < 0) return nullptr; |
| 674 Variable* var = DeclareFunctionVar(name); |
| 675 DCHECK_EQ(mode, var->mode()); |
| 676 var->AllocateTo(VariableLocation::CONTEXT, index); |
| 677 return var; |
| 678 } else { |
| 679 return nullptr; |
| 680 } |
618 } | 681 } |
619 | 682 |
620 | 683 |
621 Variable* Scope::Lookup(const AstRawString* name) { | 684 Variable* Scope::Lookup(const AstRawString* name) { |
622 for (Scope* scope = this; | 685 for (Scope* scope = this; |
623 scope != NULL; | 686 scope != NULL; |
624 scope = scope->outer_scope()) { | 687 scope = scope->outer_scope()) { |
625 Variable* var = scope->LookupLocal(name); | 688 Variable* var = scope->LookupLocal(name); |
626 if (var != NULL) return var; | 689 if (var != NULL) return var; |
627 } | 690 } |
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 function != nullptr && function->IsContextSlot(); | 1650 function != nullptr && function->IsContextSlot(); |
1588 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1651 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1589 (is_function_var_in_context ? 1 : 0); | 1652 (is_function_var_in_context ? 1 : 0); |
1590 } | 1653 } |
1591 | 1654 |
1592 | 1655 |
1593 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1656 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1594 | 1657 |
1595 } // namespace internal | 1658 } // namespace internal |
1596 } // namespace v8 | 1659 } // namespace v8 |
OLD | NEW |