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 } |
289 DCHECK(context->previous()->IsNativeContext()); | 293 DCHECK(context->previous()->IsNativeContext()); |
290 break; | 294 break; |
291 } else if (context->IsFunctionContext()) { | 295 } else if (context->IsFunctionContext()) { |
292 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), | 296 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), |
293 isolate); | 297 isolate); |
294 // TODO(neis): For an eval scope, we currently create an ordinary function | 298 // TODO(neis): For an eval scope, we currently create an ordinary function |
295 // context. This is wrong and needs to be fixed. | 299 // context. This is wrong and needs to be fixed. |
296 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 300 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
297 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 301 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
298 scope_info->scope_type() == EVAL_SCOPE); | 302 scope_info->scope_type() == EVAL_SCOPE); |
(...skipping 15 matching lines...) Expand all Loading... |
314 } else { | 318 } else { |
315 DCHECK(context->IsCatchContext()); | 319 DCHECK(context->IsCatchContext()); |
316 String* name = context->catch_name(); | 320 String* name = context->catch_name(); |
317 outer_scope = new (zone) | 321 outer_scope = new (zone) |
318 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); | 322 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); |
319 } | 323 } |
320 if (current_scope != nullptr) { | 324 if (current_scope != nullptr) { |
321 outer_scope->AddInnerScope(current_scope); | 325 outer_scope->AddInnerScope(current_scope); |
322 } | 326 } |
323 current_scope = outer_scope; | 327 current_scope = outer_scope; |
| 328 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
324 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | 329 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
325 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | 330 current_scope->scope_info_ = Handle<ScopeInfo>::null(); |
326 } | 331 } |
327 if (innermost_scope == nullptr) innermost_scope = current_scope; | 332 if (innermost_scope == nullptr) innermost_scope = current_scope; |
328 context = context->previous(); | 333 context = context->previous(); |
329 } | 334 } |
330 | 335 |
331 if (innermost_scope == nullptr) return script_scope; | 336 if (innermost_scope == nullptr) return script_scope; |
332 script_scope->AddInnerScope(current_scope); | 337 script_scope->AddInnerScope(current_scope); |
333 script_scope->PropagateScopeInfo(); | 338 script_scope->PropagateScopeInfo(); |
334 return innermost_scope; | 339 return innermost_scope; |
335 } | 340 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 Handle<String> name_handle(scope_info_->FunctionName(), isolate); | 396 Handle<String> name_handle(scope_info_->FunctionName(), isolate); |
392 const AstRawString* name = ast_value_factory->GetString(name_handle); | 397 const AstRawString* name = ast_value_factory->GetString(name_handle); |
393 VariableMode mode; | 398 VariableMode mode; |
394 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); | 399 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); |
395 if (index >= 0) { | 400 if (index >= 0) { |
396 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); | 401 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); |
397 DCHECK_EQ(mode, result->mode()); | 402 DCHECK_EQ(mode, result->mode()); |
398 result->AllocateTo(VariableLocation::CONTEXT, index); | 403 result->AllocateTo(VariableLocation::CONTEXT, index); |
399 } | 404 } |
400 } | 405 } |
401 | |
402 scope_info_ = Handle<ScopeInfo>::null(); | |
403 } | 406 } |
404 | 407 |
405 DeclarationScope* Scope::AsDeclarationScope() { | 408 DeclarationScope* Scope::AsDeclarationScope() { |
406 DCHECK(is_declaration_scope()); | 409 DCHECK(is_declaration_scope()); |
407 return static_cast<DeclarationScope*>(this); | 410 return static_cast<DeclarationScope*>(this); |
408 } | 411 } |
409 | 412 |
410 const DeclarationScope* Scope::AsDeclarationScope() const { | 413 const DeclarationScope* Scope::AsDeclarationScope() const { |
411 DCHECK(is_declaration_scope()); | 414 DCHECK(is_declaration_scope()); |
412 return static_cast<const DeclarationScope*>(this); | 415 return static_cast<const DeclarationScope*>(this); |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 } | 605 } |
603 | 606 |
604 | 607 |
605 void Scope::PropagateUsageFlagsToScope(Scope* other) { | 608 void Scope::PropagateUsageFlagsToScope(Scope* other) { |
606 DCHECK_NOT_NULL(other); | 609 DCHECK_NOT_NULL(other); |
607 DCHECK(!already_resolved_); | 610 DCHECK(!already_resolved_); |
608 DCHECK(!other->already_resolved_); | 611 DCHECK(!other->already_resolved_); |
609 if (calls_eval()) other->RecordEvalCall(); | 612 if (calls_eval()) other->RecordEvalCall(); |
610 } | 613 } |
611 | 614 |
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 | |
666 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { | 615 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { |
667 if (function_ != nullptr && function_->raw_name() == name) { | 616 if (function_ != nullptr && function_->raw_name() == name) return function_; |
668 return function_; | 617 return nullptr; |
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 } | |
681 } | 618 } |
682 | 619 |
683 | 620 |
684 Variable* Scope::Lookup(const AstRawString* name) { | 621 Variable* Scope::Lookup(const AstRawString* name) { |
685 for (Scope* scope = this; | 622 for (Scope* scope = this; |
686 scope != NULL; | 623 scope != NULL; |
687 scope = scope->outer_scope()) { | 624 scope = scope->outer_scope()) { |
688 Variable* var = scope->LookupLocal(name); | 625 Variable* var = scope->LookupLocal(name); |
689 if (var != NULL) return var; | 626 if (var != NULL) return var; |
690 } | 627 } |
(...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 function != nullptr && function->IsContextSlot(); | 1587 function != nullptr && function->IsContextSlot(); |
1651 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1588 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1652 (is_function_var_in_context ? 1 : 0); | 1589 (is_function_var_in_context ? 1 : 0); |
1653 } | 1590 } |
1654 | 1591 |
1655 | 1592 |
1656 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1593 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1657 | 1594 |
1658 } // namespace internal | 1595 } // namespace internal |
1659 } // namespace v8 | 1596 } // namespace v8 |
OLD | NEW |