5 #include "src/ast/scopes.h" 9 #include "src/accessors.h" 10 #include "src/ast/ast.h" 11 #include "src/base/optional.h" 12 #include "src/bootstrapper.h" 13 #include "src/counters.h" 14 #include "src/message-template.h" 15 #include "src/objects-inl.h" 16 #include "src/objects/module-inl.h" 17 #include "src/objects/scope-info.h" 18 #include "src/parsing/parse-info.h" 19 #include "src/parsing/preparsed-scope-data.h" 20 #include "src/zone/zone-list-inl.h" 26 bool IsLexical(Variable* variable) {
27 if (variable == Scope::kDummyPreParserLexicalVariable)
return true;
28 if (variable == Scope::kDummyPreParserVariable)
return false;
29 return IsLexicalVariableMode(variable->mode());
42 VariableMap::VariableMap(Zone* zone)
43 : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
45 Variable* VariableMap::Declare(Zone* zone, Scope* scope,
46 const AstRawString* name, VariableMode mode,
48 InitializationFlag initialization_flag,
49 MaybeAssignedFlag maybe_assigned_flag,
50 base::ThreadedList<Variable>* variable_list) {
55 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
56 ZoneAllocationPolicy(zone));
57 if (p->value ==
nullptr) {
59 DCHECK_EQ(name, p->key);
60 Variable* variable =
new (zone) Variable(
61 scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
62 if (variable_list) variable_list->Add(variable);
65 return reinterpret_cast<Variable*
>(p->value);
68 Variable* VariableMap::DeclareName(Zone* zone,
const AstRawString* name,
71 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
72 ZoneAllocationPolicy(zone));
73 if (p->value ==
nullptr) {
75 DCHECK_EQ(name, p->key);
76 p->value = mode == VariableMode::kVar
77 ? Scope::kDummyPreParserVariable
78 : Scope::kDummyPreParserLexicalVariable;
80 return reinterpret_cast<Variable*
>(p->value);
83 void VariableMap::Remove(Variable* var) {
84 const AstRawString* name = var->raw_name();
85 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
88 void VariableMap::Add(Zone* zone, Variable* var) {
89 const AstRawString* name = var->raw_name();
91 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
92 ZoneAllocationPolicy(zone));
93 DCHECK_NULL(p->value);
94 DCHECK_EQ(name, p->key);
98 Variable* VariableMap::Lookup(
const AstRawString* name) {
99 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
101 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
102 DCHECK_NOT_NULL(p->value);
103 return reinterpret_cast<Variable*
>(p->value);
108 void SloppyBlockFunctionMap::Delegate::set_statement(Statement* statement) {
109 if (statement_ !=
nullptr) {
110 statement_->set_statement(statement);
114 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
115 : ZoneHashMap(8, ZoneAllocationPolicy(zone)), count_(0) {}
117 void SloppyBlockFunctionMap::Declare(Zone* zone,
const AstRawString* name,
119 SloppyBlockFunctionStatement* statement) {
120 auto* delegate =
new (zone) Delegate(scope, statement, count_++);
124 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
125 ZoneAllocationPolicy(zone));
126 delegate->set_next(static_cast<SloppyBlockFunctionMap::Delegate*>(p->value));
133 Scope::Scope(Zone* zone)
135 outer_scope_(nullptr),
137 scope_type_(SCRIPT_SCOPE) {
141 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
143 outer_scope_(outer_scope),
145 scope_type_(scope_type) {
146 DCHECK_NE(SCRIPT_SCOPE, scope_type);
148 set_language_mode(outer_scope->language_mode());
149 outer_scope_->AddInnerScope(
this);
152 DeclarationScope::DeclarationScope(Zone* zone,
153 AstValueFactory* ast_value_factory)
154 : Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
155 DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
160 DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE,
this);
163 DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
164 ScopeType scope_type,
165 FunctionKind function_kind)
166 : Scope(zone, outer_scope, scope_type),
167 function_kind_(function_kind),
169 DCHECK_NE(scope_type, SCRIPT_SCOPE);
173 bool DeclarationScope::IsDeclaredParameter(
const AstRawString* name) {
177 return params_.Contains(variables_.Lookup(name));
180 ModuleScope::ModuleScope(DeclarationScope* script_scope,
181 AstValueFactory* ast_value_factory)
182 : DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
184 Zone* zone = ast_value_factory->zone();
185 module_descriptor_ =
new (zone) ModuleDescriptor(zone);
186 set_language_mode(LanguageMode::kStrict);
187 DeclareThis(ast_value_factory);
190 ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
191 AstValueFactory* avfactory)
192 : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info) {
193 Zone* zone = avfactory->zone();
194 Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(), isolate);
196 set_language_mode(LanguageMode::kStrict);
197 module_descriptor_ =
new (zone) ModuleDescriptor(zone);
200 Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
201 for (
int i = 0, n = special_exports->length();
i < n; ++
i) {
202 Handle<ModuleInfoEntry> serialized_entry(
203 ModuleInfoEntry::cast(special_exports->get(
i)), isolate);
204 module_descriptor_->AddSpecialExport(
205 ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
211 module_descriptor_->DeserializeRegularExports(isolate, avfactory,
215 Handle<FixedArray> namespace_imports(module_info->namespace_imports(),
217 for (
int i = 0, n = namespace_imports->length();
i < n; ++
i) {
218 Handle<ModuleInfoEntry> serialized_entry(
219 ModuleInfoEntry::cast(namespace_imports->get(
i)), isolate);
220 module_descriptor_->AddNamespaceImport(
221 ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
227 Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
228 for (
int i = 0, n = regular_imports->length();
i < n; ++
i) {
229 Handle<ModuleInfoEntry> serialized_entry(
230 ModuleInfoEntry::cast(regular_imports->get(
i)), isolate);
231 module_descriptor_->AddRegularImport(ModuleDescriptor::Entry::Deserialize(
232 isolate, avfactory, serialized_entry));
236 Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
238 outer_scope_(nullptr),
240 scope_info_(scope_info),
241 scope_type_(scope_type) {
242 DCHECK(!scope_info.is_null());
245 already_resolved_ =
true;
247 if (scope_info->CallsSloppyEval()) scope_calls_eval_ =
true;
248 set_language_mode(scope_info->language_mode());
249 num_heap_slots_ = scope_info->ContextLength();
250 DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
253 must_use_preparsed_scope_data_ =
true;
256 DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
257 Handle<ScopeInfo> scope_info)
258 : Scope(zone, scope_type, scope_info),
259 function_kind_(scope_info->function_kind()),
261 DCHECK_NE(scope_type, SCRIPT_SCOPE);
265 Scope::Scope(Zone* zone,
const AstRawString* catch_variable_name,
266 MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
268 outer_scope_(nullptr),
270 scope_info_(scope_info),
271 scope_type_(CATCH_SCOPE) {
274 already_resolved_ =
true;
280 Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
281 kCreatedInitialized, maybe_assigned);
282 AllocateHeapSlot(variable);
285 void DeclarationScope::SetDefaults() {
286 is_declaration_scope_ =
true;
287 has_simple_parameters_ =
true;
289 force_eager_compilation_ =
false;
290 has_arguments_parameter_ =
false;
291 scope_uses_super_property_ =
false;
293 sloppy_block_function_map_ =
nullptr;
295 new_target_ =
nullptr;
297 arguments_ =
nullptr;
298 rare_data_ =
nullptr;
299 should_eager_compile_ =
false;
300 was_lazily_parsed_ =
false;
301 is_skipped_function_ =
false;
302 preparsed_scope_data_builder_ =
nullptr;
304 DeclarationScope* outer_declaration_scope =
305 outer_scope_ ? outer_scope_->GetDeclarationScope() :
nullptr;
306 is_being_lazily_parsed_ =
307 outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
312 void Scope::SetDefaults() {
314 scope_name_ =
nullptr;
315 already_resolved_ =
false;
316 needs_migration_ =
false;
318 inner_scope_ =
nullptr;
320 unresolved_list_.Clear();
322 start_position_ = kNoSourcePosition;
323 end_position_ = kNoSourcePosition;
325 num_stack_slots_ = 0;
326 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
328 set_language_mode(LanguageMode::kSloppy);
330 scope_calls_eval_ =
false;
331 scope_nonlinear_ =
false;
333 is_debug_evaluate_scope_ =
false;
335 inner_scope_calls_eval_ =
false;
336 force_context_allocation_ =
false;
337 force_context_allocation_for_parameters_ =
false;
339 is_declaration_scope_ =
false;
341 must_use_preparsed_scope_data_ =
false;
344 bool Scope::HasSimpleParameters() {
345 DeclarationScope* scope = GetClosureScope();
346 return !scope->is_function_scope() || scope->has_simple_parameters();
349 bool DeclarationScope::ShouldEagerCompile()
const {
350 return force_eager_compilation_ || should_eager_compile_;
353 void DeclarationScope::set_should_eager_compile() {
354 should_eager_compile_ = !was_lazily_parsed_;
357 void DeclarationScope::set_asm_module() {
361 bool Scope::IsAsmModule()
const {
362 return is_function_scope() && AsDeclarationScope()->asm_module();
365 bool Scope::ContainsAsmModule()
const {
366 if (IsAsmModule())
return true;
369 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
371 if (!scope->is_function_scope() ||
372 scope->AsDeclarationScope()->ShouldEagerCompile()) {
373 if (scope->ContainsAsmModule())
return true;
380 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
381 ScopeInfo scope_info,
382 DeclarationScope* script_scope,
383 AstValueFactory* ast_value_factory,
384 DeserializationMode deserialization_mode) {
386 Scope* current_scope =
nullptr;
387 Scope* innermost_scope =
nullptr;
388 Scope* outer_scope =
nullptr;
389 while (!scope_info.is_null()) {
390 if (scope_info->scope_type() == WITH_SCOPE) {
393 new (zone) Scope(zone, WITH_SCOPE, handle(scope_info, isolate));
397 if (scope_info->IsDebugEvaluateScope()) {
398 outer_scope->set_is_debug_evaluate_scope();
400 }
else if (scope_info->scope_type() == SCRIPT_SCOPE) {
404 if (deserialization_mode == DeserializationMode::kIncludingVariables) {
405 script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
407 DCHECK(!scope_info->HasOuterScopeInfo());
409 }
else if (scope_info->scope_type() == FUNCTION_SCOPE) {
410 outer_scope =
new (zone)
411 DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
412 if (scope_info->IsAsmModule())
413 outer_scope->AsDeclarationScope()->set_asm_module();
414 }
else if (scope_info->scope_type() == EVAL_SCOPE) {
415 outer_scope =
new (zone)
416 DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
417 }
else if (scope_info->scope_type() == BLOCK_SCOPE) {
418 if (scope_info->is_declaration_scope()) {
419 outer_scope =
new (zone)
420 DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
423 new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
425 }
else if (scope_info->scope_type() == MODULE_SCOPE) {
426 outer_scope =
new (zone)
427 ModuleScope(isolate, handle(scope_info, isolate), ast_value_factory);
429 DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
430 DCHECK_EQ(scope_info->ContextLocalCount(), 1);
431 DCHECK_EQ(scope_info->ContextLocalMode(0), VariableMode::kVar);
432 DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
433 String name = scope_info->ContextLocalName(0);
434 MaybeAssignedFlag maybe_assigned =
435 scope_info->ContextLocalMaybeAssignedFlag(0);
436 outer_scope =
new (zone)
437 Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
438 maybe_assigned, handle(scope_info, isolate));
440 if (deserialization_mode == DeserializationMode::kScopesOnly) {
441 outer_scope->scope_info_ = Handle<ScopeInfo>::null();
443 if (current_scope !=
nullptr) {
444 outer_scope->AddInnerScope(current_scope);
446 current_scope = outer_scope;
447 if (innermost_scope ==
nullptr) innermost_scope = current_scope;
448 scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
452 if (deserialization_mode == DeserializationMode::kIncludingVariables &&
453 script_scope->scope_info_.is_null()) {
454 Handle<ScriptContextTable> table(
455 isolate->native_context()->script_context_table(), isolate);
456 Handle<Context> first = ScriptContextTable::GetContext(isolate, table, 0);
457 Handle<ScopeInfo> scope_info(first->scope_info(), isolate);
458 script_scope->SetScriptScopeInfo(scope_info);
461 if (innermost_scope ==
nullptr)
return script_scope;
462 script_scope->AddInnerScope(current_scope);
463 return innermost_scope;
466 DeclarationScope* Scope::AsDeclarationScope() {
467 DCHECK(is_declaration_scope());
468 return static_cast<DeclarationScope*
>(
this);
471 const DeclarationScope* Scope::AsDeclarationScope()
const {
472 DCHECK(is_declaration_scope());
473 return static_cast<const DeclarationScope*
>(
this);
476 ModuleScope* Scope::AsModuleScope() {
477 DCHECK(is_module_scope());
478 return static_cast<ModuleScope*
>(
this);
481 const ModuleScope* Scope::AsModuleScope()
const {
482 DCHECK(is_module_scope());
483 return static_cast<const ModuleScope*
>(
this);
486 int Scope::num_parameters()
const {
487 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
490 void DeclarationScope::DeclareSloppyBlockFunction(
491 const AstRawString* name, Scope* scope,
492 SloppyBlockFunctionStatement* statement) {
493 if (sloppy_block_function_map_ ==
nullptr) {
494 sloppy_block_function_map_ =
495 new (zone()->New(
sizeof(SloppyBlockFunctionMap)))
496 SloppyBlockFunctionMap(zone());
498 sloppy_block_function_map_->Declare(zone(), name, scope, statement);
501 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
502 DCHECK(is_sloppy(language_mode()));
503 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
504 (is_block_scope() && outer_scope()->is_function_scope()));
505 DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
506 DCHECK_EQ(factory ==
nullptr, is_being_lazily_parsed_);
508 SloppyBlockFunctionMap* map = sloppy_block_function_map();
509 if (map ==
nullptr)
return;
511 const bool has_simple_parameters = HasSimpleParameters();
515 ZoneMap<int, const AstRawString*> names_to_declare(zone());
519 for (ZoneHashMap::Entry* p = map->Start(); p !=
nullptr; p = map->Next(p)) {
520 const AstRawString* name =
static_cast<AstRawString*
>(p->key);
533 if (!has_simple_parameters) {
534 if (outer_scope_->LookupLocal(name) !=
nullptr) {
538 if (IsDeclaredParameter(name)) {
543 bool declaration_queued =
false;
546 auto delegates =
static_cast<SloppyBlockFunctionMap::Delegate*
>(p->value);
548 DeclarationScope* decl_scope =
this;
549 while (decl_scope->is_eval_scope()) {
550 decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
552 Scope* outer_scope = decl_scope->outer_scope();
554 for (SloppyBlockFunctionMap::Delegate* delegate = delegates;
555 delegate !=
nullptr; delegate = delegate->next()) {
557 Scope* query_scope = delegate->scope()->outer_scope();
558 Variable* var =
nullptr;
559 bool should_hoist =
true;
567 var = query_scope->LookupInScopeOrScopeInfo(name);
568 if (var !=
nullptr && IsLexical(var)) {
569 should_hoist =
false;
572 query_scope = query_scope->outer_scope();
573 }
while (query_scope != outer_scope);
575 if (!should_hoist)
continue;
577 if (!declaration_queued) {
578 declaration_queued =
true;
579 names_to_declare.insert({delegate->index(), name});
583 DCHECK(!is_being_lazily_parsed_);
584 Assignment* assignment = factory->NewAssignment(
585 Token::ASSIGN, NewUnresolved(factory, name),
586 delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
587 assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
588 Statement* statement =
589 factory->NewExpressionStatement(assignment, kNoSourcePosition);
590 delegate->set_statement(statement);
595 if (names_to_declare.empty())
return;
597 for (
const auto& index_and_name : names_to_declare) {
598 const AstRawString* name = index_and_name.second;
600 DCHECK(!is_being_lazily_parsed_);
601 VariableProxy* proxy = factory->NewVariableProxy(name, NORMAL_VARIABLE);
603 factory->NewVariableDeclaration(proxy, kNoSourcePosition);
607 DeclareVariable(declaration, VariableMode::kVar,
608 Variable::DefaultInitializationFlag(VariableMode::kVar),
612 DCHECK(is_being_lazily_parsed_);
613 Variable* var = DeclareVariableName(name, VariableMode::kVar);
614 if (var != kDummyPreParserVariable &&
615 var != kDummyPreParserLexicalVariable) {
616 var->set_maybe_assigned();
622 void DeclarationScope::AttachOuterScopeInfo(ParseInfo* info, Isolate* isolate) {
623 DCHECK(scope_info_.is_null());
624 Handle<ScopeInfo> outer_scope_info;
625 if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
629 info->ast_value_factory()->Internalize(isolate);
631 DeclarationScope* script_scope =
new (info->zone())
632 DeclarationScope(info->zone(), info->ast_value_factory());
633 info->set_script_scope(script_scope);
634 ReplaceOuterScope(Scope::DeserializeScopeChain(
635 isolate, info->zone(), *outer_scope_info, script_scope,
636 info->ast_value_factory(),
637 Scope::DeserializationMode::kIncludingVariables));
639 DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
640 SetScriptScopeInfo(outer_scope_info);
645 bool DeclarationScope::Analyze(ParseInfo* info) {
646 RuntimeCallTimerScope runtimeTimer(
647 info->runtime_call_stats(),
648 info->on_background_thread()
649 ? RuntimeCallCounterId::kCompileBackgroundScopeAnalysis
650 : RuntimeCallCounterId::kCompileScopeAnalysis);
651 DCHECK_NOT_NULL(info->literal());
652 DeclarationScope* scope = info->literal()->scope();
654 base::Optional<AllowHandleDereference> allow_deref;
655 if (!info->maybe_outer_scope_info().is_null()) {
657 allow_deref.emplace();
660 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
661 AstNodeFactory factory(info->ast_value_factory(), info->zone());
662 scope->HoistSloppyBlockFunctions(&factory);
669 DCHECK(scope->scope_type() == SCRIPT_SCOPE ||
670 scope->outer_scope()->scope_type() == SCRIPT_SCOPE ||
671 scope->outer_scope()->already_resolved_);
674 scope->set_should_eager_compile();
676 if (scope->must_use_preparsed_scope_data_) {
677 DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
678 allow_deref.emplace();
679 info->consumed_preparsed_scope_data()->RestoreScopeAllocationData(scope);
682 if (!scope->AllocateVariables(info))
return false;
685 if (info->is_native() ? FLAG_print_builtin_scopes : FLAG_print_scopes) {
686 PrintF(
"Global scope:\n");
689 scope->CheckScopePositions();
696 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
697 DCHECK(!already_resolved_);
698 DCHECK(is_declaration_scope());
699 DCHECK(has_this_declaration());
701 bool derived_constructor = IsDerivedConstructor(function_kind_);
703 Declare(zone(), ast_value_factory->this_string(),
704 derived_constructor ? VariableMode::kConst : VariableMode::kVar,
706 derived_constructor ? kNeedsInitialization : kCreatedInitialized);
710 void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
711 DCHECK(is_function_scope());
712 DCHECK(!is_arrow_scope());
714 arguments_ = LookupLocal(ast_value_factory->arguments_string());
715 if (arguments_ ==
nullptr) {
719 arguments_ = Declare(zone(), ast_value_factory->arguments_string(),
721 }
else if (IsLexical(arguments_)) {
724 arguments_ =
nullptr;
728 void DeclarationScope::DeclareDefaultFunctionVariables(
729 AstValueFactory* ast_value_factory) {
730 DCHECK(is_function_scope());
731 DCHECK(!is_arrow_scope());
733 DeclareThis(ast_value_factory);
734 new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
735 VariableMode::kConst);
737 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
738 IsAccessorFunction(function_kind_)) {
739 EnsureRareData()->this_function =
740 Declare(zone(), ast_value_factory->this_function_string(),
741 VariableMode::kConst);
745 Variable* DeclarationScope::DeclareFunctionVar(
const AstRawString* name,
747 DCHECK(is_function_scope());
748 DCHECK_NULL(function_);
749 if (cache ==
nullptr) cache =
this;
750 DCHECK_NULL(cache->variables_.Lookup(name));
751 VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
753 function_ =
new (zone())
754 Variable(
this, name, VariableMode::kConst, kind, kCreatedInitialized);
755 if (calls_sloppy_eval()) {
756 cache->NonLocal(name, VariableMode::kDynamic);
758 cache->variables_.Add(zone(), function_);
763 Variable* DeclarationScope::DeclareGeneratorObjectVar(
764 const AstRawString* name) {
765 DCHECK(is_function_scope() || is_module_scope());
766 DCHECK_NULL(generator_object_var());
768 Variable* result = EnsureRareData()->generator_object =
769 NewTemporary(name, kNotAssigned);
770 result->set_is_used();
774 bool Scope::HasBeenRemoved()
const {
775 if (sibling() ==
this) {
776 DCHECK_NULL(inner_scope_);
777 DCHECK(is_block_scope());
783 Scope* Scope::GetUnremovedScope() {
785 while (scope !=
nullptr && scope->HasBeenRemoved()) {
786 scope = scope->outer_scope();
788 DCHECK_NOT_NULL(scope);
792 Scope* Scope::FinalizeBlockScope() {
793 DCHECK(is_block_scope());
794 DCHECK(!HasBeenRemoved());
796 if (variables_.occupancy() > 0 ||
797 (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
802 outer_scope()->RemoveInnerScope(
this);
805 if (inner_scope_ !=
nullptr) {
806 Scope* scope = inner_scope_;
807 scope->outer_scope_ = outer_scope();
808 while (scope->sibling_ !=
nullptr) {
809 scope = scope->sibling_;
810 scope->outer_scope_ = outer_scope();
812 scope->sibling_ = outer_scope()->inner_scope_;
813 outer_scope()->inner_scope_ = inner_scope_;
814 inner_scope_ =
nullptr;
818 if (!unresolved_list_.is_empty()) {
819 outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
820 unresolved_list_.Clear();
823 if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ =
true;
827 DCHECK(!scope_calls_eval_ || !is_declaration_scope() ||
828 !is_sloppy(language_mode()));
835 DCHECK(HasBeenRemoved());
840 void DeclarationScope::AddLocal(Variable* var) {
841 DCHECK(!already_resolved_);
843 DCHECK_EQ(GetClosureScope(),
this);
847 void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
848 DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
849 DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
850 DCHECK_EQ(new_parent, new_parent->GetClosureScope());
851 DCHECK_NULL(new_parent->inner_scope_);
852 DCHECK(new_parent->unresolved_list_.is_empty());
853 DCHECK(new_parent->locals_.is_empty());
854 Scope* inner_scope = new_parent->sibling_;
855 if (inner_scope != top_inner_scope_) {
856 for (; inner_scope->sibling() != top_inner_scope_;
857 inner_scope = inner_scope->sibling()) {
858 inner_scope->outer_scope_ = new_parent;
859 if (inner_scope->inner_scope_calls_eval_) {
860 new_parent->inner_scope_calls_eval_ =
true;
862 DCHECK_NE(inner_scope, new_parent);
864 inner_scope->outer_scope_ = new_parent;
865 if (inner_scope->inner_scope_calls_eval_) {
866 new_parent->inner_scope_calls_eval_ =
true;
868 new_parent->inner_scope_ = new_parent->sibling_;
869 inner_scope->sibling_ =
nullptr;
872 new_parent->sibling_ = top_inner_scope_;
875 Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
876 new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
880 DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
881 new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
882 for (Variable* local : new_parent->locals_) {
883 DCHECK_EQ(VariableMode::kTemporary, local->mode());
884 DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
885 DCHECK_NE(local->scope(), new_parent);
886 local->set_scope(new_parent);
888 outer_closure->locals_.Rewind(top_local_);
891 if (outer_scope_and_calls_eval_.GetPayload()) {
892 new_parent->scope_calls_eval_ =
true;
893 new_parent->inner_scope_calls_eval_ =
true;
899 void Scope::ReplaceOuterScope(Scope* outer) {
900 DCHECK_NOT_NULL(outer);
901 DCHECK_NOT_NULL(outer_scope_);
902 DCHECK(!already_resolved_);
903 outer_scope_->RemoveInnerScope(
this);
904 outer->AddInnerScope(
this);
905 outer_scope_ = outer;
908 Variable* Scope::LookupInScopeInfo(
const AstRawString* name, Scope* cache) {
909 DCHECK(!scope_info_.is_null());
910 DCHECK_NULL(cache->variables_.Lookup(name));
912 Handle<String> name_handle = name->string();
918 VariableLocation location;
921 InitializationFlag init_flag;
922 MaybeAssignedFlag maybe_assigned_flag;
925 location = VariableLocation::CONTEXT;
926 index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
927 &init_flag, &maybe_assigned_flag);
931 if (!found && scope_type() == MODULE_SCOPE) {
932 location = VariableLocation::MODULE;
933 index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
934 &maybe_assigned_flag);
939 index = scope_info_->FunctionContextSlotIndex(*name_handle);
940 if (index < 0)
return nullptr;
941 Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
942 DCHECK_EQ(VariableMode::kConst, var->mode());
943 var->AllocateTo(VariableLocation::CONTEXT, index);
944 return cache->variables_.Lookup(name);
947 VariableKind kind = NORMAL_VARIABLE;
948 if (location == VariableLocation::CONTEXT &&
949 index == scope_info_->ReceiverContextSlotIndex()) {
950 kind = THIS_VARIABLE;
955 Variable* var = cache->variables_.Declare(zone(),
this, name, mode, kind,
956 init_flag, maybe_assigned_flag);
957 var->AllocateTo(location, index);
961 Variable* DeclarationScope::DeclareParameter(
const AstRawString* name,
963 bool is_optional,
bool is_rest,
964 AstValueFactory* ast_value_factory,
966 DCHECK(!already_resolved_);
967 DCHECK(is_function_scope() || is_module_scope());
969 DCHECK(!is_optional || !is_rest);
970 DCHECK(!is_being_lazily_parsed_);
971 DCHECK(!was_lazily_parsed_);
973 if (mode == VariableMode::kTemporary) {
974 var = NewTemporary(name);
976 DCHECK_EQ(mode, VariableMode::kVar);
977 var = Declare(zone(), name, mode);
980 var->set_initializer_position(position);
981 params_.Add(var, zone());
982 if (name == ast_value_factory->arguments_string()) {
983 has_arguments_parameter_ =
true;
988 Variable* DeclarationScope::DeclareParameterName(
989 const AstRawString* name,
bool is_rest, AstValueFactory* ast_value_factory,
990 bool declare_as_local,
bool add_parameter) {
991 DCHECK(!already_resolved_);
992 DCHECK(is_function_scope() || is_module_scope());
993 DCHECK(!has_rest_ || is_rest);
994 DCHECK(is_being_lazily_parsed_);
996 if (name == ast_value_factory->arguments_string()) {
997 has_arguments_parameter_ =
true;
1000 if (declare_as_local) {
1001 var = Declare(zone(), name, VariableMode::kVar);
1003 var =
new (zone()) Variable(
this, name, VariableMode::kTemporary,
1004 NORMAL_VARIABLE, kCreatedInitialized);
1006 if (add_parameter) {
1007 params_.Add(var, zone());
1012 Variable* Scope::DeclareLocal(
const AstRawString* name, VariableMode mode,
1013 InitializationFlag init_flag) {
1014 DCHECK(!already_resolved_);
1019 DCHECK(IsDeclaredVariableMode(mode));
1020 DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
1021 mode == VariableMode::kVar || mode == VariableMode::kLet ||
1022 mode == VariableMode::kConst);
1023 DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1024 return Declare(zone(), name, mode, NORMAL_VARIABLE, init_flag);
1027 Variable* Scope::DeclareVariable(
1028 Declaration* declaration, VariableMode mode, InitializationFlag init,
1029 bool* sloppy_mode_block_scope_function_redefinition,
bool* ok) {
1030 DCHECK(IsDeclaredVariableMode(mode));
1031 DCHECK(!already_resolved_);
1032 DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
1033 DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1035 if (mode == VariableMode::kVar && !is_declaration_scope()) {
1036 return GetDeclarationScope()->DeclareVariable(
1037 declaration, mode, init, sloppy_mode_block_scope_function_redefinition,
1040 DCHECK(!is_catch_scope());
1041 DCHECK(!is_with_scope());
1042 DCHECK(is_declaration_scope() ||
1043 (IsLexicalVariableMode(mode) && is_block_scope()));
1045 VariableProxy* proxy = declaration->proxy();
1046 DCHECK_NOT_NULL(proxy->raw_name());
1047 const AstRawString* name = proxy->raw_name();
1056 if (is_script_scope() || is_module_scope()) {
1057 if (mode != VariableMode::kConst) proxy->set_is_assigned();
1060 Variable* var = LookupLocal(name);
1062 if (V8_LIKELY(var ==
nullptr)) {
1063 if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
1064 mode == VariableMode::kVar)) {
1070 Variable(
this, name, mode, NORMAL_VARIABLE, init, kMaybeAssigned);
1071 var->AllocateTo(VariableLocation::LOOKUP, -1);
1074 var = DeclareLocal(name, mode, init);
1077 var->set_maybe_assigned();
1078 if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
1079 IsLexicalVariableMode(var->mode()))) {
1100 SloppyBlockFunctionMap* map =
1101 GetDeclarationScope()->sloppy_block_function_map();
1103 map !=
nullptr && declaration->IsFunctionDeclaration() &&
1104 declaration->AsFunctionDeclaration()
1105 ->declares_sloppy_block_function() &&
1106 map->Lookup(const_cast<AstRawString*>(name), name->Hash()) !=
nullptr;
1107 *sloppy_mode_block_scope_function_redefinition = *ok;
1110 DCHECK_NOT_NULL(var);
1121 decls_.Add(declaration);
1126 Variable* Scope::DeclareVariableName(
const AstRawString* name,
1127 VariableMode mode) {
1128 DCHECK(IsDeclaredVariableMode(mode));
1129 DCHECK(!already_resolved_);
1130 DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1132 if (mode == VariableMode::kVar && !is_declaration_scope()) {
1133 return GetDeclarationScope()->DeclareVariableName(name, mode);
1135 DCHECK(!is_with_scope());
1136 DCHECK(!is_eval_scope());
1137 DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode));
1138 DCHECK(scope_info_.is_null());
1141 Variable* var = LookupLocal(name);
1142 DCHECK_NE(var, kDummyPreParserLexicalVariable);
1143 DCHECK_NE(var, kDummyPreParserVariable);
1144 if (var ==
nullptr) {
1145 var = DeclareLocal(name, mode);
1146 }
else if (IsLexicalVariableMode(mode) ||
1147 IsLexicalVariableMode(var->mode())) {
1152 }
else if (mode == VariableMode::kVar) {
1153 var->set_maybe_assigned();
1159 void Scope::DeclareCatchVariableName(
const AstRawString* name) {
1160 DCHECK(!already_resolved_);
1161 DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1162 DCHECK(is_catch_scope());
1163 DCHECK(scope_info_.is_null());
1165 Declare(zone(), name, VariableMode::kVar);
1168 void Scope::AddUnresolved(VariableProxy* proxy) {
1169 DCHECK(!already_resolved_);
1170 DCHECK(!proxy->is_resolved());
1171 unresolved_list_.Add(proxy);
1174 Variable* DeclarationScope::DeclareDynamicGlobal(
const AstRawString* name,
1177 DCHECK(is_script_scope());
1178 return cache->variables_.Declare(zone(),
this, name,
1179 VariableMode::kDynamicGlobal, kind);
1183 bool Scope::RemoveUnresolved(VariableProxy* var) {
1184 return unresolved_list_.Remove(var);
1187 void Scope::DeleteUnresolved(VariableProxy* var) {
1188 DCHECK(unresolved_list_.Contains(var));
1189 var->mark_removed_from_unresolved();
1192 Variable* Scope::NewTemporary(
const AstRawString* name) {
1193 return NewTemporary(name, kMaybeAssigned);
1196 Variable* Scope::NewTemporary(
const AstRawString* name,
1197 MaybeAssignedFlag maybe_assigned) {
1198 DeclarationScope* scope = GetClosureScope();
1199 Variable* var =
new (zone()) Variable(scope, name, VariableMode::kTemporary,
1200 NORMAL_VARIABLE, kCreatedInitialized);
1201 scope->AddLocal(var);
1202 if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1206 Declaration* Scope::CheckConflictingVarDeclarations() {
1207 for (Declaration* decl : decls_) {
1208 VariableMode mode = decl->proxy()->var()->mode();
1214 Scope* current =
this;
1215 if (decl->IsVariableDeclaration() &&
1216 decl->AsVariableDeclaration()->AsNested() !=
nullptr) {
1217 DCHECK_EQ(mode, VariableMode::kVar);
1218 current = decl->AsVariableDeclaration()->AsNested()->scope();
1219 }
else if (IsLexicalVariableMode(mode)) {
1220 if (!is_block_scope())
continue;
1221 DCHECK(is_declaration_scope());
1222 DCHECK_EQ(outer_scope()->scope_type(), FUNCTION_SCOPE);
1223 current = outer_scope();
1229 Variable* other_var =
1230 current->variables_.Lookup(decl->proxy()->raw_name());
1231 if (other_var !=
nullptr && IsLexicalVariableMode(other_var->mode())) {
1234 if (current->is_declaration_scope())
break;
1235 current = current->outer_scope();
1241 Declaration* Scope::CheckLexDeclarationsConflictingWith(
1242 const ZonePtrList<const AstRawString>& names) {
1243 DCHECK(is_block_scope());
1244 for (
int i = 0;
i < names.length(); ++
i) {
1245 Variable* var = LookupLocal(names.at(
i));
1246 if (var !=
nullptr) {
1248 DCHECK(IsLexicalVariableMode(var->mode()));
1249 const AstRawString* name = names.at(
i);
1250 for (Declaration* decl : decls_) {
1251 if (decl->proxy()->raw_name() == name)
return decl;
1259 bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1262 if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1264 if (!ResolveVariablesRecursively(info)) {
1265 DCHECK(info->pending_error_handler()->has_pending_error());
1268 AllocateVariablesRecursively();
1273 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1274 const Scope* outer)
const {
1281 for (
const Scope* s =
this; s != outer; s = s->outer_scope_) {
1285 if (s->is_eval_scope())
return is_sloppy(s->language_mode());
1287 if (s->is_catch_scope())
continue;
1289 if (s->is_with_scope())
continue;
1290 DCHECK(s->is_module_scope() || s->is_block_scope() ||
1291 s->is_function_scope());
1297 bool DeclarationScope::AllowsLazyCompilation()
const {
1298 return !force_eager_compilation_;
1301 int Scope::ContextChainLength(Scope* scope)
const {
1303 for (
const Scope* s =
this; s != scope; s = s->outer_scope_) {
1305 if (s->NeedsContext()) n++;
1310 int Scope::ContextChainLengthUntilOutermostSloppyEval()
const {
1314 for (
const Scope* s =
this; s !=
nullptr; s = s->outer_scope()) {
1315 if (!s->NeedsContext())
continue;
1317 if (s->is_declaration_scope() &&
1318 s->AsDeclarationScope()->calls_sloppy_eval()) {
1326 DeclarationScope* Scope::GetDeclarationScope() {
1327 Scope* scope =
this;
1328 while (!scope->is_declaration_scope()) {
1329 scope = scope->outer_scope();
1331 return scope->AsDeclarationScope();
1334 const DeclarationScope* Scope::GetClosureScope()
const {
1335 const Scope* scope =
this;
1336 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1337 scope = scope->outer_scope();
1339 return scope->AsDeclarationScope();
1342 DeclarationScope* Scope::GetClosureScope() {
1343 Scope* scope =
this;
1344 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1345 scope = scope->outer_scope();
1347 return scope->AsDeclarationScope();
1350 bool Scope::NeedsScopeInfo()
const {
1351 DCHECK(!already_resolved_);
1352 DCHECK(GetClosureScope()->ShouldEagerCompile());
1355 if (is_function_scope())
return true;
1356 return NeedsContext();
1359 bool Scope::ShouldBanArguments() {
1360 return GetReceiverScope()->should_ban_arguments();
1363 DeclarationScope* Scope::GetReceiverScope() {
1364 Scope* scope =
this;
1365 while (!scope->is_script_scope() &&
1366 (!scope->is_function_scope() ||
1367 scope->AsDeclarationScope()->is_arrow_scope())) {
1368 scope = scope->outer_scope();
1370 return scope->AsDeclarationScope();
1373 Scope* Scope::GetOuterScopeWithContext() {
1374 Scope* scope = outer_scope_;
1375 while (scope && !scope->NeedsContext()) {
1376 scope = scope->outer_scope();
1381 void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1382 Isolate* isolate, ParseInfo* info,
1383 Handle<StringSet>* non_locals) {
1386 if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1392 is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
1396 for (VariableProxy* proxy : unresolved_list_) {
1397 DCHECK(!proxy->is_resolved());
1399 Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1400 if (var ==
nullptr) {
1401 *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1406 ResolveTo(info, proxy, var);
1407 if (!var->is_dynamic() && lookup !=
this) var->ForceContextAllocation();
1412 unresolved_list_.Clear();
1414 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
1415 scope->CollectNonLocals(max_outer_scope, isolate, info, non_locals);
1419 void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1420 AstNodeFactory* ast_node_factory,
1421 UnresolvedList* new_unresolved_list) {
1422 DCHECK_IMPLIES(is_declaration_scope(),
1423 !AsDeclarationScope()->was_lazily_parsed());
1425 for (VariableProxy* proxy = unresolved_list_.first(); proxy !=
nullptr;
1426 proxy = proxy->next_unresolved()) {
1427 DCHECK(!proxy->is_resolved());
1429 Lookup<kParsedScope>(proxy,
this, max_outer_scope->outer_scope());
1430 if (var ==
nullptr) {
1434 if (!max_outer_scope->outer_scope()->is_script_scope() ||
1435 proxy->is_private_name()) {
1436 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1437 new_unresolved_list->Add(copy);
1439 }
else if (var != Scope::kDummyPreParserVariable &&
1440 var != Scope::kDummyPreParserLexicalVariable) {
1442 if (proxy->is_assigned()) var->set_maybe_assigned();
1447 unresolved_list_.Clear();
1449 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
1450 scope->AnalyzePartially(max_outer_scope, ast_node_factory,
1451 new_unresolved_list);
1455 Handle<StringSet> DeclarationScope::CollectNonLocals(
1456 Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
1457 Scope::CollectNonLocals(
this, isolate, info, &non_locals);
1461 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1463 DCHECK(is_function_scope());
1466 if (!aborted || !IsArrowFunction(function_kind_)) {
1473 inner_scope_ =
nullptr;
1474 unresolved_list_.Clear();
1475 sloppy_block_function_map_ =
nullptr;
1476 rare_data_ =
nullptr;
1479 DCHECK_NE(zone_, ast_value_factory->zone());
1480 zone_->ReleaseMemory();
1484 zone_ = ast_value_factory->zone();
1485 variables_.Reset(ZoneAllocationPolicy(zone_));
1486 if (!IsArrowFunction(function_kind_)) {
1487 has_simple_parameters_ =
true;
1488 DeclareDefaultFunctionVariables(ast_value_factory);
1493 variables_.Invalidate();
1497 needs_migration_ =
false;
1498 is_being_lazily_parsed_ =
false;
1501 was_lazily_parsed_ = !aborted;
1504 void Scope::SavePreParsedScopeData() {
1505 if (PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(
this)) {
1506 AsDeclarationScope()->SavePreParsedScopeDataForDeclarationScope();
1509 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
1510 scope->SavePreParsedScopeData();
1514 void DeclarationScope::SavePreParsedScopeDataForDeclarationScope() {
1515 if (preparsed_scope_data_builder_ !=
nullptr) {
1516 preparsed_scope_data_builder_->SaveScopeAllocationData(
this);
1520 void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) {
1521 DCHECK(!force_eager_compilation_);
1522 UnresolvedList new_unresolved_list;
1523 if (!IsArrowFunction(function_kind_) &&
1524 (!outer_scope_->is_script_scope() ||
1525 (preparsed_scope_data_builder_ !=
nullptr &&
1526 preparsed_scope_data_builder_->ContainsInnerFunctions()))) {
1530 Scope::AnalyzePartially(
this, ast_node_factory, &new_unresolved_list);
1533 if (function_ !=
nullptr) {
1534 function_ = ast_node_factory->CopyVariable(function_);
1537 SavePreParsedScopeData();
1541 if (FLAG_print_scopes) {
1542 PrintF(
"Inner function scope:\n");
1547 ResetAfterPreparsing(ast_node_factory->ast_value_factory(),
false);
1549 unresolved_list_ = std::move(new_unresolved_list);
1555 const char* Header(ScopeType scope_type, FunctionKind function_kind,
1556 bool is_declaration_scope) {
1557 switch (scope_type) {
1558 case EVAL_SCOPE:
return "eval";
1560 case FUNCTION_SCOPE:
1561 if (IsGeneratorFunction(function_kind))
return "function*";
1562 if (IsAsyncFunction(function_kind))
return "async function";
1563 if (IsArrowFunction(function_kind))
return "arrow";
1565 case MODULE_SCOPE:
return "module";
1566 case SCRIPT_SCOPE:
return "global";
1567 case CATCH_SCOPE:
return "catch";
1568 case BLOCK_SCOPE:
return is_declaration_scope ?
"varblock" :
"block";
1569 case WITH_SCOPE:
return "with";
1574 void Indent(
int n,
const char* str) { PrintF(
"%*s%s", n,
"", str); }
1576 void PrintName(
const AstRawString* name) {
1577 PrintF(
"%.*s", name->length(), name->raw_data());
1580 void PrintLocation(Variable* var) {
1581 switch (var->location()) {
1582 case VariableLocation::UNALLOCATED:
1584 case VariableLocation::PARAMETER:
1585 PrintF(
"parameter[%d]", var->index());
1587 case VariableLocation::LOCAL:
1588 PrintF(
"local[%d]", var->index());
1590 case VariableLocation::CONTEXT:
1591 PrintF(
"context[%d]", var->index());
1593 case VariableLocation::LOOKUP:
1596 case VariableLocation::MODULE:
1602 void PrintVar(
int indent, Variable* var) {
1603 Indent(indent, VariableMode2String(var->mode()));
1605 if (var->raw_name()->IsEmpty())
1606 PrintF(
".%p", reinterpret_cast<void*>(var));
1608 PrintName(var->raw_name());
1609 PrintF(
"; // (%p) ", reinterpret_cast<void*>(var));
1611 bool comma = !var->IsUnallocated();
1612 if (var->has_forced_context_allocation()) {
1613 if (comma) PrintF(
", ");
1614 PrintF(
"forced context allocation");
1617 if (var->maybe_assigned() == kNotAssigned) {
1618 if (comma) PrintF(
", ");
1619 PrintF(
"never assigned");
1622 if (var->initialization_flag() == kNeedsInitialization &&
1623 !var->binding_needs_init()) {
1624 if (comma) PrintF(
", ");
1625 PrintF(
"hole initialization elided");
1630 void PrintMap(
int indent,
const char* label, VariableMap* map,
bool locals,
1631 Variable* function_var) {
1632 bool printed_label =
false;
1633 for (VariableMap::Entry* p = map->Start(); p !=
nullptr; p = map->Next(p)) {
1634 Variable* var =
reinterpret_cast<Variable*
>(p->value);
1635 if (var == function_var)
continue;
1636 if (var == Scope::kDummyPreParserVariable ||
1637 var == Scope::kDummyPreParserLexicalVariable) {
1640 bool local = !IsDynamicVariableMode(var->mode());
1641 if ((locals ? local : !local) &&
1642 (var->is_used() || !var->IsUnallocated())) {
1643 if (!printed_label) {
1644 Indent(indent, label);
1645 printed_label =
true;
1647 PrintVar(indent, var);
1654 void DeclarationScope::PrintParameters() {
1656 for (
int i = 0;
i < params_.length();
i++) {
1657 if (
i > 0) PrintF(
", ");
1658 const AstRawString* name = params_[
i]->raw_name();
1659 if (name->IsEmpty())
1660 PrintF(
".%p", reinterpret_cast<void*>(params_[
i]));
1667 void Scope::Print(
int n) {
1668 int n0 = (n > 0 ? n : 0);
1672 FunctionKind function_kind = is_function_scope()
1673 ? AsDeclarationScope()->function_kind()
1675 Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1676 if (scope_name_ !=
nullptr && !scope_name_->IsEmpty()) {
1678 PrintName(scope_name_);
1682 Variable*
function =
nullptr;
1683 if (is_function_scope()) {
1684 AsDeclarationScope()->PrintParameters();
1685 function = AsDeclarationScope()->function_var();
1688 PrintF(
" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(
this),
1689 start_position(), end_position());
1691 Indent(n1,
"// is hidden\n");
1695 if (
function !=
nullptr) {
1696 Indent(n1,
"// (local) function name: ");
1697 PrintName(function->raw_name());
1702 if (is_strict(language_mode())) {
1703 Indent(n1,
"// strict mode scope\n");
1705 if (IsAsmModule()) Indent(n1,
"// scope is an asm module\n");
1706 if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
1707 Indent(n1,
"// scope calls sloppy 'eval'\n");
1709 if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) {
1710 Indent(n1,
"// scope needs home object\n");
1712 if (inner_scope_calls_eval_) Indent(n1,
"// inner scope calls 'eval'\n");
1713 if (is_declaration_scope()) {
1714 DeclarationScope* scope = AsDeclarationScope();
1715 if (scope->was_lazily_parsed()) Indent(n1,
"// lazily parsed\n");
1716 if (scope->ShouldEagerCompile()) Indent(n1,
"// will be compiled\n");
1718 if (num_stack_slots_ > 0) {
1720 PrintF(
"%d stack slots\n", num_stack_slots_);
1722 if (num_heap_slots_ > 0) {
1724 PrintF(
"%d heap slots\n", num_heap_slots_);
1728 if (
function !=
nullptr) {
1729 Indent(n1,
"// function var:\n");
1730 PrintVar(n1,
function);
1735 bool printed_header =
false;
1736 for (Variable* local : locals_) {
1737 if (local->mode() != VariableMode::kTemporary)
continue;
1738 if (!printed_header) {
1739 printed_header =
true;
1740 Indent(n1,
"// temporary vars:\n");
1742 PrintVar(n1, local);
1746 if (variables_.occupancy() > 0) {
1747 PrintMap(n1,
"// local vars:\n", &variables_,
true,
function);
1748 PrintMap(n1,
"// dynamic vars:\n", &variables_,
false,
function);
1753 for (Scope* scope = inner_scope_; scope !=
nullptr;
1754 scope = scope->sibling_) {
1763 void Scope::CheckScopePositions() {
1765 if (!is_hidden() && inner_scope_ ==
nullptr) {
1766 DCHECK_NE(kNoSourcePosition, start_position());
1767 DCHECK_NE(kNoSourcePosition, end_position());
1769 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
1770 scope->CheckScopePositions();
1774 void Scope::CheckZones() {
1775 DCHECK(!needs_migration_);
1776 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
1777 if (scope->is_declaration_scope() &&
1778 scope->AsDeclarationScope()->was_lazily_parsed()) {
1779 DCHECK_NULL(scope->zone());
1780 DCHECK_NULL(scope->inner_scope_);
1783 scope->CheckZones();
1788 Variable* Scope::NonLocal(
const AstRawString* name, VariableMode mode) {
1790 DCHECK(IsDynamicVariableMode(mode));
1791 Variable* var = variables_.Declare(zone(),
nullptr, name, mode);
1793 var->AllocateTo(VariableLocation::LOOKUP, -1);
1798 template <Scope::ScopeLookupMode mode>
1799 Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
1800 Scope* outer_scope_end, Scope* entry_point,
1801 bool force_context_allocation) {
1802 if (mode == kDeserializedScope) {
1803 Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
1804 if (var !=
nullptr)
return var;
1808 DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
1816 if (mode == kDeserializedScope &&
1817 V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
1818 return entry_point->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1822 Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
1823 : scope->LookupInScopeInfo(
1824 proxy->raw_name(), entry_point);
1829 if (var !=
nullptr) {
1830 if (mode == kParsedScope && force_context_allocation &&
1831 !var->is_dynamic()) {
1832 var->ForceContextAllocation();
1837 if (scope->outer_scope_ == outer_scope_end)
break;
1839 DCHECK(!scope->is_script_scope());
1840 if (V8_UNLIKELY(scope->is_with_scope())) {
1841 return LookupWith(proxy, scope, outer_scope_end, entry_point,
1842 force_context_allocation);
1844 if (V8_UNLIKELY(scope->is_declaration_scope() &&
1845 scope->AsDeclarationScope()->calls_sloppy_eval())) {
1846 return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
1847 force_context_allocation);
1850 force_context_allocation |= scope->is_function_scope();
1851 scope = scope->outer_scope_;
1853 if (mode == kParsedScope && !scope->scope_info_.is_null()) {
1854 return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
1861 if (mode == kParsedScope && !scope->is_script_scope()) {
1864 if (V8_UNLIKELY(proxy->is_private_name()))
return nullptr;
1867 return scope->AsDeclarationScope()->DeclareDynamicGlobal(
1868 proxy->raw_name(), NORMAL_VARIABLE,
1869 mode == kDeserializedScope ? entry_point : scope);
1872 template Variable* Scope::Lookup<Scope::kParsedScope>(
1873 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1874 Scope* entry_point,
bool force_context_allocation);
1875 template Variable* Scope::Lookup<Scope::kDeserializedScope>(
1876 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1877 Scope* entry_point,
bool force_context_allocation);
1880 bool CanBeShadowed(Scope* scope, Variable* var) {
1881 if (var ==
nullptr)
return false;
1884 if (var == Scope::kDummyPreParserVariable ||
1885 var == Scope::kDummyPreParserLexicalVariable) {
1886 DCHECK(scope->GetDeclarationScope()->is_being_lazily_parsed());
1892 return !var->is_this();
1896 Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
1897 Scope* outer_scope_end, Scope* entry_point,
1898 bool force_context_allocation) {
1899 DCHECK(scope->is_with_scope());
1902 scope->outer_scope_->scope_info_.is_null()
1903 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1904 nullptr, force_context_allocation)
1905 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1906 outer_scope_end, entry_point);
1908 if (!CanBeShadowed(scope, var))
return var;
1916 if (!var->is_dynamic() && var->IsUnallocated()) {
1917 DCHECK(!scope->already_resolved_);
1919 var->ForceContextAllocation();
1920 if (proxy->is_assigned()) var->set_maybe_assigned();
1922 if (entry_point !=
nullptr) entry_point->variables_.Remove(var);
1923 Scope* target = entry_point ==
nullptr ? scope : entry_point;
1924 return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1927 Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
1928 Scope* outer_scope_end, Scope* entry_point,
1929 bool force_context_allocation) {
1930 DCHECK(scope->is_declaration_scope() &&
1931 scope->AsDeclarationScope()->calls_sloppy_eval());
1935 Scope* entry = entry_point ==
nullptr ? scope->outer_scope_ : entry_point;
1937 scope->outer_scope_->scope_info_.is_null()
1938 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1939 nullptr, force_context_allocation)
1940 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1941 outer_scope_end, entry);
1942 if (!CanBeShadowed(scope, var))
return var;
1951 if (var->IsGlobalObjectProperty()) {
1952 Scope* target = entry_point ==
nullptr ? scope : entry_point;
1953 return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
1956 if (var->is_dynamic())
return var;
1958 Variable* invalidated = var;
1959 if (entry_point !=
nullptr) entry_point->variables_.Remove(invalidated);
1961 Scope* target = entry_point ==
nullptr ? scope : entry_point;
1962 var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
1963 var->set_local_if_not_shadowed(invalidated);
1968 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1969 DCHECK(info->script_scope()->is_script_scope());
1970 DCHECK(!proxy->is_resolved());
1971 Variable* var = Lookup<kParsedScope>(proxy,
this,
nullptr);
1972 if (var ==
nullptr) {
1973 DCHECK(proxy->is_private_name());
1974 info->pending_error_handler()->ReportMessageAt(
1975 proxy->position(), proxy->position() + 1,
1976 MessageTemplate::kInvalidPrivateFieldAccess, proxy->raw_name(),
1980 ResolveTo(info, proxy, var);
1986 void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
1987 proxy->set_needs_hole_check();
1988 var->ForceHoleInitialization();
1991 void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1992 if (var->mode() == VariableMode::kDynamicLocal) {
1997 DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
1998 return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
2001 if (var->initialization_flag() == kCreatedInitialized)
return;
2006 if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
2007 return SetNeedsHoleCheck(var, proxy);
2028 if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
2029 return SetNeedsHoleCheck(var, proxy);
2032 if (var->is_this()) {
2033 DCHECK(IsDerivedConstructor(scope->GetClosureScope()->function_kind()));
2035 return SetNeedsHoleCheck(var, proxy);
2039 DCHECK_NE(var->initializer_position(), kNoSourcePosition);
2040 DCHECK_NE(proxy->position(), kNoSourcePosition);
2042 if (var->scope()->is_nonlinear() ||
2043 var->initializer_position() >= proxy->position()) {
2044 return SetNeedsHoleCheck(var, proxy);
2050 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
2052 if (info->is_native()) {
2055 DCHECK_NOT_NULL(outer_scope());
2057 if (var->IsGlobalObjectProperty()) {
2060 Handle<String> name = proxy->raw_name()->string();
2061 FATAL(
"Unbound variable: '%s' in native script.",
2062 name->ToCString().get());
2064 VariableLocation location = var->location();
2065 DCHECK(location == VariableLocation::LOCAL ||
2066 location == VariableLocation::CONTEXT ||
2067 location == VariableLocation::PARAMETER ||
2068 location == VariableLocation::UNALLOCATED);
2072 DCHECK_NOT_NULL(var);
2073 UpdateNeedsHoleCheck(var, proxy,
this);
2077 bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
2078 DCHECK(info->script_scope()->is_script_scope());
2082 if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2083 DCHECK_EQ(variables_.occupancy(), 0);
2084 for (VariableProxy* proxy : unresolved_list_) {
2085 Variable* var = Lookup<kParsedScope>(proxy, outer_scope(),
nullptr);
2086 if (var ==
nullptr) {
2087 info->pending_error_handler()->ReportMessageAt(
2088 proxy->position(), proxy->position() + 1,
2089 MessageTemplate::kInvalidPrivateFieldAccess, proxy->raw_name(),
2091 DCHECK(proxy->is_private_name());
2094 if (!var->is_dynamic()) {
2096 var->ForceContextAllocation();
2097 if (proxy->is_assigned()) var->set_maybe_assigned();
2102 for (VariableProxy* proxy : unresolved_list_) {
2103 if (!ResolveVariable(info, proxy))
return false;
2107 for (Scope* scope = inner_scope_; scope !=
nullptr;
2108 scope = scope->sibling_) {
2109 if (!scope->ResolveVariablesRecursively(info))
return false;
2115 bool Scope::MustAllocate(Variable* var) {
2116 if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
2119 DCHECK(var->location() != VariableLocation::MODULE);
2123 if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
2124 (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2126 if (inner_scope_calls_eval_) var->set_maybe_assigned();
2128 DCHECK(!var->has_forced_context_allocation() || var->is_used());
2130 return !var->IsGlobalObjectProperty() && var->is_used();
2134 bool Scope::MustAllocateInContext(Variable* var) {
2142 if (var->mode() == VariableMode::kTemporary)
return false;
2143 if (is_catch_scope())
return true;
2144 if ((is_script_scope() || is_eval_scope()) &&
2145 IsLexicalVariableMode(var->mode())) {
2148 return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2152 void Scope::AllocateStackSlot(Variable* var) {
2153 if (is_block_scope()) {
2154 outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2156 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2161 void Scope::AllocateHeapSlot(Variable* var) {
2162 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2165 void DeclarationScope::AllocateParameterLocals() {
2166 DCHECK(is_function_scope());
2168 bool has_mapped_arguments =
false;
2169 if (arguments_ !=
nullptr) {
2170 DCHECK(!is_arrow_scope());
2171 if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2176 has_mapped_arguments =
2177 GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2181 arguments_ =
nullptr;
2189 for (
int i = num_parameters() - 1;
i >= 0; --
i) {
2190 Variable* var = params_[
i];
2191 DCHECK(!has_rest_ || var != rest_parameter());
2192 DCHECK_EQ(
this, var->scope());
2193 if (has_mapped_arguments) {
2195 var->set_maybe_assigned();
2196 var->ForceContextAllocation();
2198 AllocateParameter(var,
i);
2202 void DeclarationScope::AllocateParameter(Variable* var,
int index) {
2203 if (MustAllocate(var)) {
2204 if (has_forced_context_allocation_for_parameters() ||
2205 MustAllocateInContext(var)) {
2206 DCHECK(var->IsUnallocated() || var->IsContextSlot());
2207 if (var->IsUnallocated()) {
2208 AllocateHeapSlot(var);
2211 DCHECK(var->IsUnallocated() || var->IsParameter());
2212 if (var->IsUnallocated()) {
2213 var->AllocateTo(VariableLocation::PARAMETER, index);
2219 void DeclarationScope::AllocateReceiver() {
2220 if (!has_this_declaration())
return;
2221 DCHECK_NOT_NULL(receiver());
2222 DCHECK_EQ(receiver()->scope(),
this);
2223 AllocateParameter(receiver(), -1);
2226 void Scope::AllocateNonParameterLocal(Variable* var) {
2227 DCHECK(var->scope() ==
this);
2228 if (var->IsUnallocated() && MustAllocate(var)) {
2229 if (MustAllocateInContext(var)) {
2230 AllocateHeapSlot(var);
2231 DCHECK_IMPLIES(is_catch_scope(),
2232 var->index() == Context::THROWN_OBJECT_INDEX);
2234 AllocateStackSlot(var);
2239 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2240 for (Variable* local : locals_) {
2241 AllocateNonParameterLocal(local);
2244 if (is_declaration_scope()) {
2245 AsDeclarationScope()->AllocateLocals();
2249 void DeclarationScope::AllocateLocals() {
2254 if (function_ !=
nullptr && MustAllocate(function_)) {
2255 AllocateNonParameterLocal(function_);
2257 function_ =
nullptr;
2260 DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2261 !rest_parameter()->IsUnallocated());
2263 if (new_target_ !=
nullptr && !MustAllocate(new_target_)) {
2264 new_target_ =
nullptr;
2267 NullifyRareVariableIf(RareVariable::kThisFunction,
2268 [=](Variable* var) {
return !MustAllocate(var); });
2271 void ModuleScope::AllocateModuleVariables() {
2272 for (
const auto& it : module()->regular_imports()) {
2273 Variable* var = LookupLocal(it.first);
2274 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2275 DCHECK(!var->IsExport());
2278 for (
const auto& it : module()->regular_exports()) {
2279 Variable* var = LookupLocal(it.first);
2280 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2281 DCHECK(var->IsExport());
2285 void Scope::AllocateVariablesRecursively() {
2286 DCHECK(!already_resolved_);
2289 if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2294 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
2295 scope->AllocateVariablesRecursively();
2298 DCHECK(!already_resolved_);
2299 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
2303 if (is_declaration_scope()) {
2304 if (is_function_scope()) {
2305 AsDeclarationScope()->AllocateParameterLocals();
2307 AsDeclarationScope()->AllocateReceiver();
2309 AllocateNonParameterLocalsAndDeclaredGlobals();
2315 bool must_have_context =
2316 is_with_scope() || is_module_scope() || IsAsmModule() ||
2317 (is_function_scope() && AsDeclarationScope()->calls_sloppy_eval()) ||
2318 (is_block_scope() && is_declaration_scope() &&
2319 AsDeclarationScope()->calls_sloppy_eval());
2323 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
2324 num_heap_slots_ = 0;
2328 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2331 void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
2332 MaybeHandle<ScopeInfo> outer_scope) {
2333 DCHECK(scope_info_.is_null());
2334 MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2336 if (NeedsScopeInfo()) {
2337 scope_info_ = ScopeInfo::Create(isolate, zone(),
this, outer_scope);
2340 if (NeedsContext()) next_outer_scope = scope_info_;
2344 for (Scope* scope = inner_scope_; scope !=
nullptr; scope = scope->sibling_) {
2345 if (!scope->is_function_scope() ||
2346 scope->AsDeclarationScope()->ShouldEagerCompile()) {
2347 scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2353 void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate) {
2354 DeclarationScope* scope = info->literal()->scope();
2355 if (!scope->scope_info_.is_null())
return;
2357 MaybeHandle<ScopeInfo> outer_scope;
2358 if (scope->outer_scope_ !=
nullptr) {
2359 outer_scope = scope->outer_scope_->scope_info_;
2362 scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2368 if (scope->scope_info_.is_null()) {
2369 scope->scope_info_ =
2370 ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2375 if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2376 info->script_scope()->scope_info_ =
2377 handle(ScopeInfo::Empty(isolate), isolate);
2381 int Scope::StackLocalCount()
const {
2382 Variable*
function =
2383 is_function_scope() ? AsDeclarationScope()->function_var() :
nullptr;
2384 return num_stack_slots() -
2385 (
function !=
nullptr &&
function->IsStackLocal() ? 1 : 0);
2389 int Scope::ContextLocalCount()
const {
2390 if (num_heap_slots() == 0)
return 0;
2391 Variable*
function =
2392 is_function_scope() ? AsDeclarationScope()->function_var() :
nullptr;
2393 bool is_function_var_in_context =
2394 function !=
nullptr &&
function->IsContextSlot();
2395 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2396 (is_function_var_in_context ? 1 : 0);
2399 void*
const Scope::kDummyPreParserVariable =
reinterpret_cast<void*
>(0x1);
2400 void*
const Scope::kDummyPreParserLexicalVariable =
2401 reinterpret_cast<void*
>(0x2);