• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "src/ast/scopes.h"
6 
7 #include <set>
8 
9 #include "src/ast/ast.h"
10 #include "src/base/logging.h"
11 #include "src/base/optional.h"
12 #include "src/builtins/accessors.h"
13 #include "src/common/message-template.h"
14 #include "src/heap/local-factory-inl.h"
15 #include "src/init/bootstrapper.h"
16 #include "src/logging/counters.h"
17 #include "src/objects/module-inl.h"
18 #include "src/objects/objects-inl.h"
19 #include "src/objects/scope-info.h"
20 #include "src/objects/string-set-inl.h"
21 #include "src/parsing/parse-info.h"
22 #include "src/parsing/parser.h"
23 #include "src/parsing/preparse-data.h"
24 #include "src/zone/zone-list-inl.h"
25 #include "src/zone/zone.h"
26 
27 namespace v8 {
28 namespace internal {
29 
30 // ----------------------------------------------------------------------------
31 // Implementation of LocalsMap
32 //
33 // Note: We are storing the handle locations as key values in the hash map.
34 //       When inserting a new variable via Declare(), we rely on the fact that
35 //       the handle location remains alive for the duration of that variable
36 //       use. Because a Variable holding a handle with the same location exists
37 //       this is ensured.
38 
39 static_assert(sizeof(VariableMap) == (sizeof(void*) + 2 * sizeof(uint32_t) +
40                                       sizeof(ZoneAllocationPolicy)),
41               "Empty base optimization didn't kick in for VariableMap");
42 
VariableMap(Zone * zone)43 VariableMap::VariableMap(Zone* zone)
44     : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
45 
VariableMap(const VariableMap & other,Zone * zone)46 VariableMap::VariableMap(const VariableMap& other, Zone* zone)
47     : ZoneHashMap(other, ZoneAllocationPolicy(zone)) {}
48 
Declare(Zone * zone,Scope * scope,const AstRawString * name,VariableMode mode,VariableKind kind,InitializationFlag initialization_flag,MaybeAssignedFlag maybe_assigned_flag,IsStaticFlag is_static_flag,bool * was_added)49 Variable* VariableMap::Declare(Zone* zone, Scope* scope,
50                                const AstRawString* name, VariableMode mode,
51                                VariableKind kind,
52                                InitializationFlag initialization_flag,
53                                MaybeAssignedFlag maybe_assigned_flag,
54                                IsStaticFlag is_static_flag, bool* was_added) {
55   DCHECK_EQ(zone, allocator().zone());
56   // AstRawStrings are unambiguous, i.e., the same string is always represented
57   // by the same AstRawString*.
58   // FIXME(marja): fix the type of Lookup.
59   Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
60                                          name->Hash());
61   *was_added = p->value == nullptr;
62   if (*was_added) {
63     // The variable has not been declared yet -> insert it.
64     DCHECK_EQ(name, p->key);
65     Variable* variable =
66         zone->New<Variable>(scope, name, mode, kind, initialization_flag,
67                             maybe_assigned_flag, is_static_flag);
68     p->value = variable;
69   }
70   return reinterpret_cast<Variable*>(p->value);
71 }
72 
Remove(Variable * var)73 void VariableMap::Remove(Variable* var) {
74   const AstRawString* name = var->raw_name();
75   ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
76 }
77 
Add(Variable * var)78 void VariableMap::Add(Variable* var) {
79   const AstRawString* name = var->raw_name();
80   Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
81                                          name->Hash());
82   DCHECK_NULL(p->value);
83   DCHECK_EQ(name, p->key);
84   p->value = var;
85 }
86 
Lookup(const AstRawString * name)87 Variable* VariableMap::Lookup(const AstRawString* name) {
88   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
89   if (p != nullptr) {
90     DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
91     DCHECK_NOT_NULL(p->value);
92     return reinterpret_cast<Variable*>(p->value);
93   }
94   return nullptr;
95 }
96 
97 // ----------------------------------------------------------------------------
98 // Implementation of Scope
99 
Scope(Zone * zone)100 Scope::Scope(Zone* zone)
101     : outer_scope_(nullptr), variables_(zone), scope_type_(SCRIPT_SCOPE) {
102   SetDefaults();
103 }
104 
Scope(Zone * zone,Scope * outer_scope,ScopeType scope_type)105 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
106     : outer_scope_(outer_scope), variables_(zone), scope_type_(scope_type) {
107   DCHECK_NE(SCRIPT_SCOPE, scope_type);
108   SetDefaults();
109   set_language_mode(outer_scope->language_mode());
110   private_name_lookup_skips_outer_class_ =
111       outer_scope->is_class_scope() &&
112       outer_scope->AsClassScope()->IsParsingHeritage();
113   outer_scope_->AddInnerScope(this);
114 }
115 
DeclarationScope(Zone * zone,AstValueFactory * ast_value_factory,REPLMode repl_mode)116 DeclarationScope::DeclarationScope(Zone* zone,
117                                    AstValueFactory* ast_value_factory,
118                                    REPLMode repl_mode)
119     : Scope(zone),
120       function_kind_(repl_mode == REPLMode::kYes ? kAsyncFunction
121                                                  : kNormalFunction),
122       params_(4, zone) {
123   DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
124   SetDefaults();
125   is_repl_mode_scope_ = repl_mode == REPLMode::kYes;
126   receiver_ = DeclareDynamicGlobal(ast_value_factory->this_string(),
127                                    THIS_VARIABLE, this);
128 }
129 
DeclarationScope(Zone * zone,Scope * outer_scope,ScopeType scope_type,FunctionKind function_kind)130 DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
131                                    ScopeType scope_type,
132                                    FunctionKind function_kind)
133     : Scope(zone, outer_scope, scope_type),
134       function_kind_(function_kind),
135       params_(4, zone) {
136   DCHECK_NE(scope_type, SCRIPT_SCOPE);
137   SetDefaults();
138 }
139 
ModuleScope(DeclarationScope * script_scope,AstValueFactory * avfactory)140 ModuleScope::ModuleScope(DeclarationScope* script_scope,
141                          AstValueFactory* avfactory)
142     : DeclarationScope(avfactory->zone(), script_scope, MODULE_SCOPE, kModule),
143       module_descriptor_(avfactory->zone()->New<SourceTextModuleDescriptor>(
144           avfactory->zone())) {
145   set_language_mode(LanguageMode::kStrict);
146   DeclareThis(avfactory);
147 }
148 
ModuleScope(Isolate * isolate,Handle<ScopeInfo> scope_info,AstValueFactory * avfactory)149 ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
150                          AstValueFactory* avfactory)
151     : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info),
152       module_descriptor_(nullptr) {
153   set_language_mode(LanguageMode::kStrict);
154 }
155 
ClassScope(Zone * zone,Scope * outer_scope,bool is_anonymous)156 ClassScope::ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous)
157     : Scope(zone, outer_scope, CLASS_SCOPE),
158       rare_data_and_is_parsing_heritage_(nullptr),
159       is_anonymous_class_(is_anonymous) {
160   set_language_mode(LanguageMode::kStrict);
161 }
162 
ClassScope(Isolate * isolate,Zone * zone,AstValueFactory * ast_value_factory,Handle<ScopeInfo> scope_info)163 ClassScope::ClassScope(Isolate* isolate, Zone* zone,
164                        AstValueFactory* ast_value_factory,
165                        Handle<ScopeInfo> scope_info)
166     : Scope(zone, CLASS_SCOPE, scope_info),
167       rare_data_and_is_parsing_heritage_(nullptr) {
168   set_language_mode(LanguageMode::kStrict);
169   if (scope_info->HasClassBrand()) {
170     Variable* brand =
171         LookupInScopeInfo(ast_value_factory->dot_brand_string(), this);
172     DCHECK_NOT_NULL(brand);
173     EnsureRareData()->brand = brand;
174   }
175 
176   // If the class variable is context-allocated and its index is
177   // saved for deserialization, deserialize it.
178   if (scope_info->HasSavedClassVariableIndex()) {
179     int index = scope_info->SavedClassVariableContextLocalIndex();
180     DCHECK_GE(index, 0);
181     DCHECK_LT(index, scope_info->ContextLocalCount());
182     String name = scope_info->ContextLocalName(index);
183     DCHECK_EQ(scope_info->ContextLocalMode(index), VariableMode::kConst);
184     DCHECK_EQ(scope_info->ContextLocalInitFlag(index),
185               InitializationFlag::kNeedsInitialization);
186     DCHECK_EQ(scope_info->ContextLocalMaybeAssignedFlag(index),
187               MaybeAssignedFlag::kMaybeAssigned);
188     Variable* var = DeclareClassVariable(
189         ast_value_factory, ast_value_factory->GetString(handle(name, isolate)),
190         kNoSourcePosition);
191     var->AllocateTo(VariableLocation::CONTEXT,
192                     Context::MIN_CONTEXT_SLOTS + index);
193   }
194 }
195 
Scope(Zone * zone,ScopeType scope_type,Handle<ScopeInfo> scope_info)196 Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
197     : outer_scope_(nullptr),
198       variables_(zone),
199       scope_info_(scope_info),
200       scope_type_(scope_type) {
201   DCHECK(!scope_info.is_null());
202   SetDefaults();
203 #ifdef DEBUG
204   already_resolved_ = true;
205 #endif
206   set_language_mode(scope_info->language_mode());
207   DCHECK_EQ(ContextHeaderLength(), num_heap_slots_);
208   private_name_lookup_skips_outer_class_ =
209       scope_info->PrivateNameLookupSkipsOuterClass();
210   // We don't really need to use the preparsed scope data; this is just to
211   // shorten the recursion in SetMustUsePreparseData.
212   must_use_preparsed_scope_data_ = true;
213 }
214 
DeclarationScope(Zone * zone,ScopeType scope_type,Handle<ScopeInfo> scope_info)215 DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
216                                    Handle<ScopeInfo> scope_info)
217     : Scope(zone, scope_type, scope_info),
218       function_kind_(scope_info->function_kind()),
219       params_(0, zone) {
220   DCHECK_NE(scope_type, SCRIPT_SCOPE);
221   SetDefaults();
222   if (scope_info->SloppyEvalCanExtendVars()) {
223     DCHECK(!is_eval_scope());
224     sloppy_eval_can_extend_vars_ = true;
225   }
226 }
227 
Scope(Zone * zone,const AstRawString * catch_variable_name,MaybeAssignedFlag maybe_assigned,Handle<ScopeInfo> scope_info)228 Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
229              MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
230     : outer_scope_(nullptr),
231       variables_(zone),
232       scope_info_(scope_info),
233       scope_type_(CATCH_SCOPE) {
234   SetDefaults();
235 #ifdef DEBUG
236   already_resolved_ = true;
237 #endif
238   // Cache the catch variable, even though it's also available via the
239   // scope_info, as the parser expects that a catch scope always has the catch
240   // variable as first and only variable.
241   bool was_added;
242   Variable* variable =
243       Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
244               kCreatedInitialized, maybe_assigned, &was_added);
245   DCHECK(was_added);
246   AllocateHeapSlot(variable);
247 }
248 
SetDefaults()249 void DeclarationScope::SetDefaults() {
250   is_declaration_scope_ = true;
251   has_simple_parameters_ = true;
252   is_asm_module_ = false;
253   force_eager_compilation_ = false;
254   has_arguments_parameter_ = false;
255   scope_uses_super_property_ = false;
256   has_checked_syntax_ = false;
257   has_this_reference_ = false;
258   has_this_declaration_ =
259       (is_function_scope() && !is_arrow_scope()) || is_module_scope();
260   needs_private_name_context_chain_recalc_ = false;
261   has_rest_ = false;
262   receiver_ = nullptr;
263   new_target_ = nullptr;
264   function_ = nullptr;
265   arguments_ = nullptr;
266   rare_data_ = nullptr;
267   should_eager_compile_ = false;
268   was_lazily_parsed_ = false;
269   is_skipped_function_ = false;
270   preparse_data_builder_ = nullptr;
271 #ifdef DEBUG
272   DeclarationScope* outer_declaration_scope =
273       outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
274   is_being_lazily_parsed_ =
275       outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
276                               : false;
277 #endif
278 }
279 
SetDefaults()280 void Scope::SetDefaults() {
281 #ifdef DEBUG
282   scope_name_ = nullptr;
283   already_resolved_ = false;
284   needs_migration_ = false;
285 #endif
286   inner_scope_ = nullptr;
287   sibling_ = nullptr;
288   unresolved_list_.Clear();
289 
290   start_position_ = kNoSourcePosition;
291   end_position_ = kNoSourcePosition;
292 
293   calls_eval_ = false;
294   sloppy_eval_can_extend_vars_ = false;
295   scope_nonlinear_ = false;
296   is_hidden_ = false;
297   is_debug_evaluate_scope_ = false;
298 
299   inner_scope_calls_eval_ = false;
300   force_context_allocation_for_parameters_ = false;
301 
302   is_declaration_scope_ = false;
303 
304   private_name_lookup_skips_outer_class_ = false;
305 
306   must_use_preparsed_scope_data_ = false;
307   is_repl_mode_scope_ = false;
308 
309   deserialized_scope_uses_external_cache_ = false;
310 
311   num_stack_slots_ = 0;
312   num_heap_slots_ = ContextHeaderLength();
313 
314   set_language_mode(LanguageMode::kSloppy);
315 }
316 
HasSimpleParameters()317 bool Scope::HasSimpleParameters() {
318   DeclarationScope* scope = GetClosureScope();
319   return !scope->is_function_scope() || scope->has_simple_parameters();
320 }
321 
set_should_eager_compile()322 void DeclarationScope::set_should_eager_compile() {
323   should_eager_compile_ = !was_lazily_parsed_;
324 }
325 
set_is_asm_module()326 void DeclarationScope::set_is_asm_module() { is_asm_module_ = true; }
327 
IsAsmModule() const328 bool Scope::IsAsmModule() const {
329   return is_function_scope() && AsDeclarationScope()->is_asm_module();
330 }
331 
ContainsAsmModule() const332 bool Scope::ContainsAsmModule() const {
333   if (IsAsmModule()) return true;
334 
335   // Check inner scopes recursively
336   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
337     // Don't check inner functions which won't be eagerly compiled.
338     if (!scope->is_function_scope() ||
339         scope->AsDeclarationScope()->ShouldEagerCompile()) {
340       if (scope->ContainsAsmModule()) return true;
341     }
342   }
343 
344   return false;
345 }
346 
DeserializeScopeChain(Isolate * isolate,Zone * zone,ScopeInfo scope_info,DeclarationScope * script_scope,AstValueFactory * ast_value_factory,DeserializationMode deserialization_mode)347 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
348                                     ScopeInfo scope_info,
349                                     DeclarationScope* script_scope,
350                                     AstValueFactory* ast_value_factory,
351                                     DeserializationMode deserialization_mode) {
352   // Reconstruct the outer scope chain from a closure's context chain.
353   Scope* current_scope = nullptr;
354   Scope* innermost_scope = nullptr;
355   Scope* outer_scope = nullptr;
356   bool cache_scope_found = false;
357   while (!scope_info.is_null()) {
358     if (scope_info.scope_type() == WITH_SCOPE) {
359       if (scope_info.IsDebugEvaluateScope()) {
360         outer_scope = zone->New<DeclarationScope>(zone, FUNCTION_SCOPE,
361                                                   handle(scope_info, isolate));
362         outer_scope->set_is_debug_evaluate_scope();
363       } else {
364         // For scope analysis, debug-evaluate is equivalent to a with scope.
365         outer_scope =
366             zone->New<Scope>(zone, WITH_SCOPE, handle(scope_info, isolate));
367       }
368 
369     } else if (scope_info.scope_type() == SCRIPT_SCOPE) {
370       // If we reach a script scope, it's the outermost scope. Install the
371       // scope info of this script context onto the existing script scope to
372       // avoid nesting script scopes.
373       if (deserialization_mode == DeserializationMode::kIncludingVariables) {
374         script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
375       }
376       if (scope_info.IsReplModeScope()) script_scope->set_is_repl_mode_scope();
377       DCHECK(!scope_info.HasOuterScopeInfo());
378       break;
379     } else if (scope_info.scope_type() == FUNCTION_SCOPE) {
380       outer_scope = zone->New<DeclarationScope>(zone, FUNCTION_SCOPE,
381                                                 handle(scope_info, isolate));
382       if (scope_info.IsAsmModule()) {
383         outer_scope->AsDeclarationScope()->set_is_asm_module();
384       }
385     } else if (scope_info.scope_type() == EVAL_SCOPE) {
386       outer_scope = zone->New<DeclarationScope>(zone, EVAL_SCOPE,
387                                                 handle(scope_info, isolate));
388     } else if (scope_info.scope_type() == CLASS_SCOPE) {
389       outer_scope = zone->New<ClassScope>(isolate, zone, ast_value_factory,
390                                           handle(scope_info, isolate));
391     } else if (scope_info.scope_type() == BLOCK_SCOPE) {
392       if (scope_info.is_declaration_scope()) {
393         outer_scope = zone->New<DeclarationScope>(zone, BLOCK_SCOPE,
394                                                   handle(scope_info, isolate));
395       } else {
396         outer_scope =
397             zone->New<Scope>(zone, BLOCK_SCOPE, handle(scope_info, isolate));
398       }
399     } else if (scope_info.scope_type() == MODULE_SCOPE) {
400       outer_scope = zone->New<ModuleScope>(isolate, handle(scope_info, isolate),
401                                            ast_value_factory);
402     } else {
403       DCHECK_EQ(scope_info.scope_type(), CATCH_SCOPE);
404       DCHECK_EQ(scope_info.ContextLocalCount(), 1);
405       DCHECK_EQ(scope_info.ContextLocalMode(0), VariableMode::kVar);
406       DCHECK_EQ(scope_info.ContextLocalInitFlag(0), kCreatedInitialized);
407       String name = scope_info.ContextLocalName(0);
408       MaybeAssignedFlag maybe_assigned =
409           scope_info.ContextLocalMaybeAssignedFlag(0);
410       outer_scope = zone->New<Scope>(
411           zone, ast_value_factory->GetString(handle(name, isolate)),
412           maybe_assigned, handle(scope_info, isolate));
413     }
414     if (deserialization_mode == DeserializationMode::kScopesOnly) {
415       outer_scope->scope_info_ = Handle<ScopeInfo>::null();
416     }
417 
418     if (cache_scope_found) {
419       outer_scope->set_deserialized_scope_uses_external_cache();
420     } else {
421       DCHECK(!cache_scope_found);
422       cache_scope_found =
423           outer_scope->is_declaration_scope() && !outer_scope->is_eval_scope();
424     }
425 
426     if (current_scope != nullptr) {
427       outer_scope->AddInnerScope(current_scope);
428     }
429     current_scope = outer_scope;
430     if (innermost_scope == nullptr) innermost_scope = current_scope;
431     scope_info = scope_info.HasOuterScopeInfo() ? scope_info.OuterScopeInfo()
432                                                 : ScopeInfo();
433   }
434 
435   if (deserialization_mode == DeserializationMode::kIncludingVariables &&
436       script_scope->scope_info_.is_null()) {
437     script_scope->SetScriptScopeInfo(
438         ReadOnlyRoots(isolate).global_this_binding_scope_info_handle());
439   }
440 
441   if (innermost_scope == nullptr) return script_scope;
442   script_scope->AddInnerScope(current_scope);
443   return innermost_scope;
444 }
445 
AsDeclarationScope()446 DeclarationScope* Scope::AsDeclarationScope() {
447   DCHECK(is_declaration_scope());
448   return static_cast<DeclarationScope*>(this);
449 }
450 
AsDeclarationScope() const451 const DeclarationScope* Scope::AsDeclarationScope() const {
452   DCHECK(is_declaration_scope());
453   return static_cast<const DeclarationScope*>(this);
454 }
455 
AsModuleScope()456 ModuleScope* Scope::AsModuleScope() {
457   DCHECK(is_module_scope());
458   return static_cast<ModuleScope*>(this);
459 }
460 
AsModuleScope() const461 const ModuleScope* Scope::AsModuleScope() const {
462   DCHECK(is_module_scope());
463   return static_cast<const ModuleScope*>(this);
464 }
465 
AsClassScope()466 ClassScope* Scope::AsClassScope() {
467   DCHECK(is_class_scope());
468   return static_cast<ClassScope*>(this);
469 }
470 
AsClassScope() const471 const ClassScope* Scope::AsClassScope() const {
472   DCHECK(is_class_scope());
473   return static_cast<const ClassScope*>(this);
474 }
475 
DeclareSloppyBlockFunction(SloppyBlockFunctionStatement * sloppy_block_function)476 void DeclarationScope::DeclareSloppyBlockFunction(
477     SloppyBlockFunctionStatement* sloppy_block_function) {
478   sloppy_block_functions_.Add(sloppy_block_function);
479 }
480 
HoistSloppyBlockFunctions(AstNodeFactory * factory)481 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
482   DCHECK(is_sloppy(language_mode()));
483   DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
484          (is_block_scope() && outer_scope()->is_function_scope()));
485   DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
486   DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
487 
488   if (sloppy_block_functions_.is_empty()) return;
489 
490   // In case of complex parameters the current scope is the body scope and the
491   // parameters are stored in the outer scope.
492   Scope* parameter_scope = HasSimpleParameters() ? this : outer_scope_;
493   DCHECK(parameter_scope->is_function_scope() || is_eval_scope() ||
494          is_script_scope());
495 
496   DeclarationScope* decl_scope = GetNonEvalDeclarationScope();
497   Scope* outer_scope = decl_scope->outer_scope();
498 
499   // For each variable which is used as a function declaration in a sloppy
500   // block,
501   for (SloppyBlockFunctionStatement* sloppy_block_function :
502        sloppy_block_functions_) {
503     const AstRawString* name = sloppy_block_function->name();
504 
505     // If the variable wouldn't conflict with a lexical declaration
506     // or parameter,
507 
508     // Check if there's a conflict with a parameter.
509     Variable* maybe_parameter = parameter_scope->LookupLocal(name);
510     if (maybe_parameter != nullptr && maybe_parameter->is_parameter()) {
511       continue;
512     }
513 
514     // Check if there's a conflict with a lexical declaration
515     Scope* query_scope = sloppy_block_function->scope()->outer_scope();
516     Variable* var = nullptr;
517     bool should_hoist = true;
518 
519     // It is not sufficient to just do a Lookup on query_scope: for
520     // example, that does not prevent hoisting of the function in
521     // `{ let e; try {} catch (e) { function e(){} } }`
522     //
523     // Don't use a generic cache scope, as the cache scope would be the outer
524     // scope and we terminate the iteration there anyway.
525     do {
526       var = query_scope->LookupInScopeOrScopeInfo(name, query_scope);
527       if (var != nullptr && IsLexicalVariableMode(var->mode())) {
528         should_hoist = false;
529         break;
530       }
531       query_scope = query_scope->outer_scope();
532     } while (query_scope != outer_scope);
533 
534     if (!should_hoist) continue;
535 
536     if (factory) {
537       DCHECK(!is_being_lazily_parsed_);
538       int pos = sloppy_block_function->position();
539       bool ok = true;
540       bool was_added;
541       auto declaration = factory->NewVariableDeclaration(pos);
542       // Based on the preceding checks, it doesn't matter what we pass as
543       // sloppy_mode_block_scope_function_redefinition.
544       Variable* var = DeclareVariable(
545           declaration, name, pos, VariableMode::kVar, NORMAL_VARIABLE,
546           Variable::DefaultInitializationFlag(VariableMode::kVar), &was_added,
547           nullptr, &ok);
548       DCHECK(ok);
549       VariableProxy* source =
550           factory->NewVariableProxy(sloppy_block_function->var());
551       VariableProxy* target = factory->NewVariableProxy(var);
552       Assignment* assignment = factory->NewAssignment(
553           sloppy_block_function->init(), target, source, pos);
554       assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
555       Statement* statement = factory->NewExpressionStatement(assignment, pos);
556       sloppy_block_function->set_statement(statement);
557     } else {
558       DCHECK(is_being_lazily_parsed_);
559       bool was_added;
560       Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
561       if (sloppy_block_function->init() == Token::ASSIGN) {
562         var->SetMaybeAssigned();
563       }
564     }
565   }
566 }
567 
Analyze(ParseInfo * info)568 bool DeclarationScope::Analyze(ParseInfo* info) {
569   RuntimeCallTimerScope runtimeTimer(
570       info->runtime_call_stats(), RuntimeCallCounterId::kCompileScopeAnalysis,
571       RuntimeCallStats::kThreadSpecific);
572   DCHECK_NOT_NULL(info->literal());
573   DeclarationScope* scope = info->literal()->scope();
574 
575   base::Optional<AllowHandleDereference> allow_deref;
576 #ifdef DEBUG
577   if (scope->outer_scope() && !scope->outer_scope()->scope_info_.is_null()) {
578     allow_deref.emplace();
579   }
580 #endif
581 
582   if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
583     AstNodeFactory factory(info->ast_value_factory(), info->zone());
584     scope->HoistSloppyBlockFunctions(&factory);
585   }
586 
587   // We are compiling one of four cases:
588   // 1) top-level code,
589   // 2) a function/eval/module on the top-level
590   // 3) a function/eval in a scope that was already resolved.
591   DCHECK(scope->is_script_scope() || scope->outer_scope()->is_script_scope() ||
592          scope->outer_scope()->already_resolved_);
593 
594   // The outer scope is never lazy.
595   scope->set_should_eager_compile();
596 
597   if (scope->must_use_preparsed_scope_data_) {
598     DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
599     allow_deref.emplace();
600     info->consumed_preparse_data()->RestoreScopeAllocationData(
601         scope, info->ast_value_factory(), info->zone());
602   }
603 
604   if (!scope->AllocateVariables(info)) return false;
605   scope->GetScriptScope()->RewriteReplGlobalVariables();
606 
607 #ifdef DEBUG
608   if (FLAG_print_scopes) {
609     PrintF("Global scope:\n");
610     scope->Print();
611   }
612   scope->CheckScopePositions();
613   scope->CheckZones();
614 #endif
615 
616   return true;
617 }
618 
DeclareThis(AstValueFactory * ast_value_factory)619 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
620   DCHECK(has_this_declaration());
621 
622   bool derived_constructor = IsDerivedConstructor(function_kind_);
623 
624   receiver_ = zone()->New<Variable>(
625       this, ast_value_factory->this_string(),
626       derived_constructor ? VariableMode::kConst : VariableMode::kVar,
627       THIS_VARIABLE,
628       derived_constructor ? kNeedsInitialization : kCreatedInitialized,
629       kNotAssigned);
630 }
631 
DeclareArguments(AstValueFactory * ast_value_factory)632 void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
633   DCHECK(is_function_scope());
634   DCHECK(!is_arrow_scope());
635 
636   // Declare 'arguments' variable which exists in all non arrow functions.  Note
637   // that it might never be accessed, in which case it won't be allocated during
638   // variable allocation.
639   bool was_added;
640   arguments_ =
641       Declare(zone(), ast_value_factory->arguments_string(), VariableMode::kVar,
642               NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
643   if (!was_added && IsLexicalVariableMode(arguments_->mode())) {
644     // Check if there's lexically declared variable named arguments to avoid
645     // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
646     arguments_ = nullptr;
647   }
648 }
649 
DeclareDefaultFunctionVariables(AstValueFactory * ast_value_factory)650 void DeclarationScope::DeclareDefaultFunctionVariables(
651     AstValueFactory* ast_value_factory) {
652   DCHECK(is_function_scope());
653   DCHECK(!is_arrow_scope());
654 
655   DeclareThis(ast_value_factory);
656   bool was_added;
657   new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
658                         VariableMode::kConst, NORMAL_VARIABLE,
659                         kCreatedInitialized, kNotAssigned, &was_added);
660   DCHECK(was_added);
661 
662   if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
663       IsAccessorFunction(function_kind_)) {
664     EnsureRareData()->this_function = Declare(
665         zone(), ast_value_factory->this_function_string(), VariableMode::kConst,
666         NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
667     DCHECK(was_added);
668   }
669 }
670 
DeclareFunctionVar(const AstRawString * name,Scope * cache)671 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
672                                                Scope* cache) {
673   DCHECK(is_function_scope());
674   DCHECK_NULL(function_);
675   if (cache == nullptr) cache = this;
676   DCHECK(this->IsOuterScopeOf(cache));
677   DCHECK_NULL(cache->variables_.Lookup(name));
678   VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
679                                                  : NORMAL_VARIABLE;
680   function_ = zone()->New<Variable>(this, name, VariableMode::kConst, kind,
681                                     kCreatedInitialized);
682   if (sloppy_eval_can_extend_vars()) {
683     cache->NonLocal(name, VariableMode::kDynamic);
684   } else {
685     cache->variables_.Add(function_);
686   }
687   return function_;
688 }
689 
DeclareGeneratorObjectVar(const AstRawString * name)690 Variable* DeclarationScope::DeclareGeneratorObjectVar(
691     const AstRawString* name) {
692   DCHECK(is_function_scope() || is_module_scope() || is_repl_mode_scope());
693   DCHECK_NULL(generator_object_var());
694 
695   Variable* result = EnsureRareData()->generator_object =
696       NewTemporary(name, kNotAssigned);
697   result->set_is_used();
698   return result;
699 }
700 
FinalizeBlockScope()701 Scope* Scope::FinalizeBlockScope() {
702   DCHECK(is_block_scope());
703 #ifdef DEBUG
704   DCHECK_NE(sibling_, this);
705 #endif
706 
707   if (variables_.occupancy() > 0 ||
708       (is_declaration_scope() &&
709        AsDeclarationScope()->sloppy_eval_can_extend_vars())) {
710     return this;
711   }
712 
713   DCHECK(!is_class_scope());
714 
715   // Remove this scope from outer scope.
716   outer_scope()->RemoveInnerScope(this);
717 
718   // Reparent inner scopes.
719   if (inner_scope_ != nullptr) {
720     Scope* scope = inner_scope_;
721     scope->outer_scope_ = outer_scope();
722     while (scope->sibling_ != nullptr) {
723       scope = scope->sibling_;
724       scope->outer_scope_ = outer_scope();
725     }
726     scope->sibling_ = outer_scope()->inner_scope_;
727     outer_scope()->inner_scope_ = inner_scope_;
728     inner_scope_ = nullptr;
729   }
730 
731   // Move unresolved variables
732   if (!unresolved_list_.is_empty()) {
733     outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
734     unresolved_list_.Clear();
735   }
736 
737   if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
738 
739   // No need to propagate sloppy_eval_can_extend_vars_, since if it was relevant
740   // to this scope we would have had to bail out at the top.
741   DCHECK(!is_declaration_scope() ||
742          !AsDeclarationScope()->sloppy_eval_can_extend_vars());
743 
744   // This block does not need a context.
745   num_heap_slots_ = 0;
746 
747   // Mark scope as removed by making it its own sibling.
748 #ifdef DEBUG
749   sibling_ = this;
750 #endif
751 
752   return nullptr;
753 }
754 
AddLocal(Variable * var)755 void DeclarationScope::AddLocal(Variable* var) {
756   DCHECK(!already_resolved_);
757   // Temporaries are only placed in ClosureScopes.
758   DCHECK_EQ(GetClosureScope(), this);
759   locals_.Add(var);
760 }
761 
Reparent(DeclarationScope * new_parent)762 void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
763   DCHECK(!IsCleared());
764   DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
765   DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
766   DCHECK_EQ(new_parent, new_parent->GetClosureScope());
767   DCHECK_NULL(new_parent->inner_scope_);
768   DCHECK(new_parent->unresolved_list_.is_empty());
769   Scope* inner_scope = new_parent->sibling_;
770   if (inner_scope != top_inner_scope_) {
771     for (; inner_scope->sibling() != top_inner_scope_;
772          inner_scope = inner_scope->sibling()) {
773       inner_scope->outer_scope_ = new_parent;
774       if (inner_scope->inner_scope_calls_eval_) {
775         new_parent->inner_scope_calls_eval_ = true;
776       }
777       DCHECK_NE(inner_scope, new_parent);
778     }
779     inner_scope->outer_scope_ = new_parent;
780     if (inner_scope->inner_scope_calls_eval_) {
781       new_parent->inner_scope_calls_eval_ = true;
782     }
783     new_parent->inner_scope_ = new_parent->sibling_;
784     inner_scope->sibling_ = nullptr;
785     // Reset the sibling rather than the inner_scope_ since we
786     // want to keep new_parent there.
787     new_parent->sibling_ = top_inner_scope_;
788   }
789 
790   Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
791   new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
792                                         top_unresolved_);
793 
794   // Move temporaries allocated for complex parameter initializers.
795   DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
796   for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
797     Variable* local = *it;
798     DCHECK_EQ(VariableMode::kTemporary, local->mode());
799     DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
800     DCHECK_NE(local->scope(), new_parent);
801     local->set_scope(new_parent);
802   }
803   new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
804   outer_closure->locals_.Rewind(top_local_);
805 
806   // Move eval calls since Snapshot's creation into new_parent.
807   if (outer_scope_and_calls_eval_->calls_eval_) {
808     new_parent->RecordDeclarationScopeEvalCall();
809     new_parent->inner_scope_calls_eval_ = true;
810   }
811 
812   // We are in the arrow function case. The calls eval we may have recorded
813   // is intended for the inner scope and we should simply restore the
814   // original "calls eval" flag of the outer scope.
815   RestoreEvalFlag();
816   Clear();
817 }
818 
ReplaceOuterScope(Scope * outer)819 void Scope::ReplaceOuterScope(Scope* outer) {
820   DCHECK_NOT_NULL(outer);
821   DCHECK_NOT_NULL(outer_scope_);
822   DCHECK(!already_resolved_);
823   outer_scope_->RemoveInnerScope(this);
824   outer->AddInnerScope(this);
825   outer_scope_ = outer;
826 }
827 
LookupInScopeInfo(const AstRawString * name,Scope * cache)828 Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
829   DCHECK(!scope_info_.is_null());
830   DCHECK(this->IsOuterScopeOf(cache));
831   DCHECK(!cache->deserialized_scope_uses_external_cache());
832   // The case where where the cache can be another scope is when the cache scope
833   // is the last scope that doesn't use an external cache.
834   DCHECK_IMPLIES(
835       cache != this,
836       cache->outer_scope()->deserialized_scope_uses_external_cache());
837   DCHECK_NULL(cache->variables_.Lookup(name));
838   DisallowHeapAllocation no_gc;
839 
840   String name_handle = *name->string();
841   ScopeInfo scope_info = *scope_info_;
842   // The Scope is backed up by ScopeInfo. This means it cannot operate in a
843   // heap-independent mode, and all strings must be internalized immediately. So
844   // it's ok to get the Handle<String> here.
845   bool found = false;
846 
847   VariableLocation location;
848   int index;
849   VariableMode mode;
850   InitializationFlag init_flag;
851   MaybeAssignedFlag maybe_assigned_flag;
852   IsStaticFlag is_static_flag;
853 
854   {
855     location = VariableLocation::CONTEXT;
856     index =
857         ScopeInfo::ContextSlotIndex(scope_info, name_handle, &mode, &init_flag,
858                                     &maybe_assigned_flag, &is_static_flag);
859     found = index >= 0;
860   }
861 
862   if (!found && is_module_scope()) {
863     location = VariableLocation::MODULE;
864     index = scope_info.ModuleIndex(name_handle, &mode, &init_flag,
865                                    &maybe_assigned_flag);
866     found = index != 0;
867   }
868 
869   if (!found) {
870     index = scope_info.FunctionContextSlotIndex(name_handle);
871     if (index < 0) return nullptr;  // Nowhere found.
872     Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
873     DCHECK_EQ(VariableMode::kConst, var->mode());
874     var->AllocateTo(VariableLocation::CONTEXT, index);
875     return cache->variables_.Lookup(name);
876   }
877 
878   if (!is_module_scope()) {
879     DCHECK_NE(index, scope_info.ReceiverContextSlotIndex());
880   }
881 
882   bool was_added;
883   Variable* var = cache->variables_.Declare(
884       zone(), this, name, mode, NORMAL_VARIABLE, init_flag, maybe_assigned_flag,
885       IsStaticFlag::kNotStatic, &was_added);
886   DCHECK(was_added);
887   var->AllocateTo(location, index);
888   return var;
889 }
890 
DeclareParameter(const AstRawString * name,VariableMode mode,bool is_optional,bool is_rest,AstValueFactory * ast_value_factory,int position)891 Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
892                                              VariableMode mode,
893                                              bool is_optional, bool is_rest,
894                                              AstValueFactory* ast_value_factory,
895                                              int position) {
896   DCHECK(!already_resolved_);
897   DCHECK(is_function_scope() || is_module_scope());
898   DCHECK(!has_rest_);
899   DCHECK(!is_optional || !is_rest);
900   DCHECK(!is_being_lazily_parsed_);
901   DCHECK(!was_lazily_parsed_);
902   Variable* var;
903   if (mode == VariableMode::kTemporary) {
904     var = NewTemporary(name);
905   } else {
906     var = LookupLocal(name);
907     DCHECK_EQ(mode, VariableMode::kVar);
908     DCHECK(var->is_parameter());
909   }
910   has_rest_ = is_rest;
911   var->set_initializer_position(position);
912   params_.Add(var, zone());
913   if (!is_rest) ++num_parameters_;
914   if (name == ast_value_factory->arguments_string()) {
915     has_arguments_parameter_ = true;
916   }
917   // Params are automatically marked as used to make sure that the debugger and
918   // function.arguments sees them.
919   // TODO(verwaest): Reevaluate whether we always need to do this, since
920   // strict-mode function.arguments does not make the arguments available.
921   var->set_is_used();
922   return var;
923 }
924 
RecordParameter(bool is_rest)925 void DeclarationScope::RecordParameter(bool is_rest) {
926   DCHECK(!already_resolved_);
927   DCHECK(is_function_scope() || is_module_scope());
928   DCHECK(is_being_lazily_parsed_);
929   DCHECK(!has_rest_);
930   has_rest_ = is_rest;
931   if (!is_rest) ++num_parameters_;
932 }
933 
DeclareLocal(const AstRawString * name,VariableMode mode,VariableKind kind,bool * was_added,InitializationFlag init_flag)934 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
935                               VariableKind kind, bool* was_added,
936                               InitializationFlag init_flag) {
937   DCHECK(!already_resolved_);
938   // Private methods should be declared with ClassScope::DeclarePrivateName()
939   DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
940   // This function handles VariableMode::kVar, VariableMode::kLet, and
941   // VariableMode::kConst modes.  VariableMode::kDynamic variables are
942   // introduced during variable allocation, and VariableMode::kTemporary
943   // variables are allocated via NewTemporary().
944   DCHECK(IsDeclaredVariableMode(mode));
945   DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
946                  mode == VariableMode::kVar || mode == VariableMode::kLet ||
947                      mode == VariableMode::kConst);
948   DCHECK(!GetDeclarationScope()->was_lazily_parsed());
949   Variable* var =
950       Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);
951 
952   // Pessimistically assume that top-level variables will be assigned and used.
953   //
954   // Top-level variables in a script can be accessed by other scripts or even
955   // become global properties. While this does not apply to top-level variables
956   // in a module (assuming they are not exported), we must still mark these as
957   // assigned because they might be accessed by a lazily parsed top-level
958   // function, which, for efficiency, we preparse without variable tracking.
959   if (is_script_scope() || is_module_scope()) {
960     if (mode != VariableMode::kConst) var->SetMaybeAssigned();
961     var->set_is_used();
962   }
963 
964   return var;
965 }
966 
DeclareVariable(Declaration * declaration,const AstRawString * name,int pos,VariableMode mode,VariableKind kind,InitializationFlag init,bool * was_added,bool * sloppy_mode_block_scope_function_redefinition,bool * ok)967 Variable* Scope::DeclareVariable(
968     Declaration* declaration, const AstRawString* name, int pos,
969     VariableMode mode, VariableKind kind, InitializationFlag init,
970     bool* was_added, bool* sloppy_mode_block_scope_function_redefinition,
971     bool* ok) {
972   // Private methods should be declared with ClassScope::DeclarePrivateName()
973   DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
974   DCHECK(IsDeclaredVariableMode(mode));
975   DCHECK(!already_resolved_);
976   DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
977   DCHECK(!GetDeclarationScope()->was_lazily_parsed());
978 
979   if (mode == VariableMode::kVar && !is_declaration_scope()) {
980     return GetDeclarationScope()->DeclareVariable(
981         declaration, name, pos, mode, kind, init, was_added,
982         sloppy_mode_block_scope_function_redefinition, ok);
983   }
984   DCHECK(!is_catch_scope());
985   DCHECK(!is_with_scope());
986   DCHECK(is_declaration_scope() ||
987          (IsLexicalVariableMode(mode) && is_block_scope()));
988 
989   DCHECK_NOT_NULL(name);
990 
991   Variable* var = LookupLocal(name);
992   // Declare the variable in the declaration scope.
993   *was_added = var == nullptr;
994   if (V8_LIKELY(*was_added)) {
995     if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
996                     mode == VariableMode::kVar)) {
997       // In a var binding in a sloppy direct eval, pollute the enclosing scope
998       // with this new binding by doing the following:
999       // The proxy is bound to a lookup variable to force a dynamic declaration
1000       // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1001       DCHECK_EQ(NORMAL_VARIABLE, kind);
1002       var = NonLocal(name, VariableMode::kDynamic);
1003       // Mark the var as used in case anyone outside the eval wants to use it.
1004       var->set_is_used();
1005     } else {
1006       // Declare the name.
1007       var = DeclareLocal(name, mode, kind, was_added, init);
1008       DCHECK(*was_added);
1009     }
1010   } else {
1011     var->SetMaybeAssigned();
1012     if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
1013                     IsLexicalVariableMode(var->mode()))) {
1014       // The name was declared in this scope before; check for conflicting
1015       // re-declarations. We have a conflict if either of the declarations is
1016       // not a var (in script scope, we also have to ignore legacy const for
1017       // compatibility). There is similar code in runtime.cc in the Declare
1018       // functions. The function CheckConflictingVarDeclarations checks for
1019       // var and let bindings from different scopes whereas this is a check
1020       // for conflicting declarations within the same scope. This check also
1021       // covers the special case
1022       //
1023       // function () { let x; { var x; } }
1024       //
1025       // because the var declaration is hoisted to the function scope where
1026       // 'x' is already bound.
1027       //
1028       // In harmony we treat re-declarations as early errors. See ES5 16 for a
1029       // definition of early errors.
1030       //
1031       // Allow duplicate function decls for web compat, see bug 4693.
1032       *ok = var->is_sloppy_block_function() &&
1033             kind == SLOPPY_BLOCK_FUNCTION_VARIABLE;
1034       *sloppy_mode_block_scope_function_redefinition = *ok;
1035     }
1036   }
1037   DCHECK_NOT_NULL(var);
1038 
1039   // We add a declaration node for every declaration. The compiler
1040   // will only generate code if necessary. In particular, declarations
1041   // for inner local variables that do not represent functions won't
1042   // result in any generated code.
1043   //
1044   // This will lead to multiple declaration nodes for the
1045   // same variable if it is declared several times. This is not a
1046   // semantic issue, but it may be a performance issue since it may
1047   // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1048   decls_.Add(declaration);
1049   declaration->set_var(var);
1050   return var;
1051 }
1052 
DeclareVariableName(const AstRawString * name,VariableMode mode,bool * was_added,VariableKind kind)1053 Variable* Scope::DeclareVariableName(const AstRawString* name,
1054                                      VariableMode mode, bool* was_added,
1055                                      VariableKind kind) {
1056   DCHECK(IsDeclaredVariableMode(mode));
1057   DCHECK(!already_resolved_);
1058   DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1059   // Private methods should be declared with ClassScope::DeclarePrivateName()
1060   DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
1061   if (mode == VariableMode::kVar && !is_declaration_scope()) {
1062     return GetDeclarationScope()->DeclareVariableName(name, mode, was_added,
1063                                                       kind);
1064   }
1065   DCHECK(!is_with_scope());
1066   DCHECK(!is_eval_scope());
1067   DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode));
1068   DCHECK(scope_info_.is_null());
1069 
1070   // Declare the variable in the declaration scope.
1071   Variable* var = DeclareLocal(name, mode, kind, was_added);
1072   if (!*was_added) {
1073     if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) {
1074       if (!var->is_sloppy_block_function() ||
1075           kind != SLOPPY_BLOCK_FUNCTION_VARIABLE) {
1076         // Duplicate functions are allowed in the sloppy mode, but if this is
1077         // not a function declaration, it's an error. This is an error PreParser
1078         // hasn't previously detected.
1079         return nullptr;
1080       }
1081       // Sloppy block function redefinition.
1082     }
1083     var->SetMaybeAssigned();
1084   }
1085   var->set_is_used();
1086   return var;
1087 }
1088 
DeclareCatchVariableName(const AstRawString * name)1089 Variable* Scope::DeclareCatchVariableName(const AstRawString* name) {
1090   DCHECK(!already_resolved_);
1091   DCHECK(is_catch_scope());
1092   DCHECK(scope_info_.is_null());
1093 
1094   bool was_added;
1095   Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE,
1096                              kCreatedInitialized, kNotAssigned, &was_added);
1097   DCHECK(was_added);
1098   return result;
1099 }
1100 
AddUnresolved(VariableProxy * proxy)1101 void Scope::AddUnresolved(VariableProxy* proxy) {
1102   DCHECK(!already_resolved_);
1103   DCHECK(!proxy->is_resolved());
1104   unresolved_list_.Add(proxy);
1105 }
1106 
DeclareDynamicGlobal(const AstRawString * name,VariableKind kind,Scope * cache)1107 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1108                                                  VariableKind kind,
1109                                                  Scope* cache) {
1110   DCHECK(is_script_scope());
1111   bool was_added;
1112   return cache->variables_.Declare(
1113       zone(), this, name, VariableMode::kDynamicGlobal, kind,
1114       kCreatedInitialized, kNotAssigned, IsStaticFlag::kNotStatic, &was_added);
1115   // TODO(neis): Mark variable as maybe-assigned?
1116 }
1117 
RemoveUnresolved(VariableProxy * var)1118 bool Scope::RemoveUnresolved(VariableProxy* var) {
1119   return unresolved_list_.Remove(var);
1120 }
1121 
DeleteUnresolved(VariableProxy * var)1122 void Scope::DeleteUnresolved(VariableProxy* var) {
1123   DCHECK(unresolved_list_.Contains(var));
1124   var->mark_removed_from_unresolved();
1125 }
1126 
NewTemporary(const AstRawString * name)1127 Variable* Scope::NewTemporary(const AstRawString* name) {
1128   return NewTemporary(name, kMaybeAssigned);
1129 }
1130 
NewTemporary(const AstRawString * name,MaybeAssignedFlag maybe_assigned)1131 Variable* Scope::NewTemporary(const AstRawString* name,
1132                               MaybeAssignedFlag maybe_assigned) {
1133   DeclarationScope* scope = GetClosureScope();
1134   Variable* var = zone()->New<Variable>(scope, name, VariableMode::kTemporary,
1135                                         NORMAL_VARIABLE, kCreatedInitialized);
1136   scope->AddLocal(var);
1137   if (maybe_assigned == kMaybeAssigned) var->SetMaybeAssigned();
1138   return var;
1139 }
1140 
CheckConflictingVarDeclarations(bool * allowed_catch_binding_var_redeclaration)1141 Declaration* DeclarationScope::CheckConflictingVarDeclarations(
1142     bool* allowed_catch_binding_var_redeclaration) {
1143   if (has_checked_syntax_) return nullptr;
1144   for (Declaration* decl : decls_) {
1145     // Lexical vs lexical conflicts within the same scope have already been
1146     // captured in Parser::Declare. The only conflicts we still need to check
1147     // are lexical vs nested var.
1148     if (decl->IsVariableDeclaration() &&
1149         decl->AsVariableDeclaration()->AsNested() != nullptr) {
1150       Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
1151       DCHECK(decl->var()->mode() == VariableMode::kVar ||
1152              decl->var()->mode() == VariableMode::kDynamic);
1153       // Iterate through all scopes until the declaration scope.
1154       do {
1155         // There is a conflict if there exists a non-VAR binding.
1156         Variable* other_var = current->LookupLocal(decl->var()->raw_name());
1157         if (current->is_catch_scope()) {
1158           *allowed_catch_binding_var_redeclaration |= other_var != nullptr;
1159           current = current->outer_scope();
1160           continue;
1161         }
1162         if (other_var != nullptr) {
1163           DCHECK(IsLexicalVariableMode(other_var->mode()));
1164           return decl;
1165         }
1166         current = current->outer_scope();
1167       } while (current != this);
1168     }
1169   }
1170 
1171   if (V8_LIKELY(!is_eval_scope())) return nullptr;
1172   if (!is_sloppy(language_mode())) return nullptr;
1173 
1174   // Var declarations in sloppy eval are hoisted to the first non-eval
1175   // declaration scope. Check for conflicts between the eval scope that
1176   // declaration scope.
1177   Scope* end = outer_scope()->GetNonEvalDeclarationScope()->outer_scope();
1178 
1179   for (Declaration* decl : decls_) {
1180     if (IsLexicalVariableMode(decl->var()->mode())) continue;
1181     Scope* current = outer_scope_;
1182     // Iterate through all scopes until and including the declaration scope.
1183     do {
1184       // There is a conflict if there exists a non-VAR binding up to the
1185       // declaration scope in which this sloppy-eval runs.
1186       //
1187       // Use the current scope as the cache, since the general cache would be
1188       // the end scope.
1189       Variable* other_var =
1190           current->LookupInScopeOrScopeInfo(decl->var()->raw_name(), current);
1191       if (other_var != nullptr && !current->is_catch_scope()) {
1192         // If this is a VAR, then we know that it doesn't conflict with
1193         // anything, so we can't conflict with anything either. The one
1194         // exception is the binding variable in catch scopes, which is handled
1195         // by the if above.
1196         if (!IsLexicalVariableMode(other_var->mode())) break;
1197         return decl;
1198       }
1199       current = current->outer_scope();
1200     } while (current != end);
1201   }
1202   return nullptr;
1203 }
1204 
FindVariableDeclaredIn(Scope * scope,VariableMode mode_limit)1205 const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope,
1206                                                   VariableMode mode_limit) {
1207   const VariableMap& variables = scope->variables_;
1208   for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr;
1209        p = variables.Next(p)) {
1210     const AstRawString* name = static_cast<const AstRawString*>(p->key);
1211     Variable* var = LookupLocal(name);
1212     if (var != nullptr && var->mode() <= mode_limit) return name;
1213   }
1214   return nullptr;
1215 }
1216 
DeserializeReceiver(AstValueFactory * ast_value_factory)1217 void DeclarationScope::DeserializeReceiver(AstValueFactory* ast_value_factory) {
1218   if (is_script_scope()) {
1219     DCHECK_NOT_NULL(receiver_);
1220     return;
1221   }
1222   DCHECK(has_this_declaration());
1223   DeclareThis(ast_value_factory);
1224   if (is_debug_evaluate_scope()) {
1225     receiver_->AllocateTo(VariableLocation::LOOKUP, -1);
1226   } else {
1227     receiver_->AllocateTo(VariableLocation::CONTEXT,
1228                           scope_info_->ReceiverContextSlotIndex());
1229   }
1230 }
1231 
AllocateVariables(ParseInfo * info)1232 bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1233   // Module variables must be allocated before variable resolution
1234   // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1235   if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1236 
1237   PrivateNameScopeIterator private_name_scope_iter(this);
1238   if (!private_name_scope_iter.Done() &&
1239       !private_name_scope_iter.GetScope()->ResolvePrivateNames(info)) {
1240     DCHECK(info->pending_error_handler()->has_pending_error());
1241     return false;
1242   }
1243 
1244   if (!ResolveVariablesRecursively(info->scope())) {
1245     DCHECK(info->pending_error_handler()->has_pending_error());
1246     return false;
1247   }
1248 
1249   // Don't allocate variables of preparsed scopes.
1250   if (!was_lazily_parsed()) AllocateVariablesRecursively();
1251 
1252   return true;
1253 }
1254 
HasThisReference() const1255 bool Scope::HasThisReference() const {
1256   if (is_declaration_scope() && AsDeclarationScope()->has_this_reference()) {
1257     return true;
1258   }
1259 
1260   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1261     if (!scope->is_declaration_scope() ||
1262         !scope->AsDeclarationScope()->has_this_declaration()) {
1263       if (scope->HasThisReference()) return true;
1264     }
1265   }
1266 
1267   return false;
1268 }
1269 
AllowsLazyParsingWithoutUnresolvedVariables(const Scope * outer) const1270 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1271     const Scope* outer) const {
1272   // If none of the outer scopes need to decide whether to context allocate
1273   // specific variables, we can preparse inner functions without unresolved
1274   // variables. Otherwise we need to find unresolved variables to force context
1275   // allocation of the matching declarations. We can stop at the outer scope for
1276   // the parse, since context allocation of those variables is already
1277   // guaranteed to be correct.
1278   for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1279     // Eval forces context allocation on all outer scopes, so we don't need to
1280     // look at those scopes. Sloppy eval makes top-level non-lexical variables
1281     // dynamic, whereas strict-mode requires context allocation.
1282     if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1283     // Catch scopes force context allocation of all variables.
1284     if (s->is_catch_scope()) continue;
1285     // With scopes do not introduce variables that need allocation.
1286     if (s->is_with_scope()) continue;
1287     DCHECK(s->is_module_scope() || s->is_block_scope() ||
1288            s->is_function_scope());
1289     return false;
1290   }
1291   return true;
1292 }
1293 
AllowsLazyCompilation() const1294 bool DeclarationScope::AllowsLazyCompilation() const {
1295   // Functions which force eager compilation and class member initializer
1296   // functions are not lazily compilable.
1297   return !force_eager_compilation_ &&
1298          !IsClassMembersInitializerFunction(function_kind());
1299 }
1300 
ContextChainLength(Scope * scope) const1301 int Scope::ContextChainLength(Scope* scope) const {
1302   int n = 0;
1303   for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1304     DCHECK_NOT_NULL(s);  // scope must be in the scope chain
1305     if (s->NeedsContext()) n++;
1306   }
1307   return n;
1308 }
1309 
ContextChainLengthUntilOutermostSloppyEval() const1310 int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1311   int result = 0;
1312   int length = 0;
1313 
1314   for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1315     if (!s->NeedsContext()) continue;
1316     length++;
1317     if (s->is_declaration_scope() &&
1318         s->AsDeclarationScope()->sloppy_eval_can_extend_vars()) {
1319       result = length;
1320     }
1321   }
1322 
1323   return result;
1324 }
1325 
GetDeclarationScope()1326 DeclarationScope* Scope::GetDeclarationScope() {
1327   Scope* scope = this;
1328   while (!scope->is_declaration_scope()) {
1329     scope = scope->outer_scope();
1330   }
1331   return scope->AsDeclarationScope();
1332 }
1333 
GetNonEvalDeclarationScope()1334 DeclarationScope* Scope::GetNonEvalDeclarationScope() {
1335   Scope* scope = this;
1336   while (!scope->is_declaration_scope() || scope->is_eval_scope()) {
1337     scope = scope->outer_scope();
1338   }
1339   return scope->AsDeclarationScope();
1340 }
1341 
GetClosureScope() const1342 const DeclarationScope* Scope::GetClosureScope() const {
1343   const Scope* scope = this;
1344   while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1345     scope = scope->outer_scope();
1346   }
1347   return scope->AsDeclarationScope();
1348 }
1349 
GetClosureScope()1350 DeclarationScope* Scope::GetClosureScope() {
1351   Scope* scope = this;
1352   while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1353     scope = scope->outer_scope();
1354   }
1355   return scope->AsDeclarationScope();
1356 }
1357 
NeedsScopeInfo() const1358 bool Scope::NeedsScopeInfo() const {
1359   DCHECK(!already_resolved_);
1360   DCHECK(GetClosureScope()->ShouldEagerCompile());
1361   // The debugger expects all functions to have scope infos.
1362   // TODO(jochen|yangguo): Remove this requirement.
1363   if (is_function_scope()) return true;
1364   return NeedsContext();
1365 }
1366 
ShouldBanArguments()1367 bool Scope::ShouldBanArguments() {
1368   return GetReceiverScope()->should_ban_arguments();
1369 }
1370 
GetReceiverScope()1371 DeclarationScope* Scope::GetReceiverScope() {
1372   Scope* scope = this;
1373   while (!scope->is_declaration_scope() ||
1374          (!scope->is_script_scope() &&
1375           !scope->AsDeclarationScope()->has_this_declaration())) {
1376     scope = scope->outer_scope();
1377   }
1378   return scope->AsDeclarationScope();
1379 }
1380 
GetScriptScope()1381 DeclarationScope* Scope::GetScriptScope() {
1382   Scope* scope = this;
1383   while (!scope->is_script_scope()) {
1384     scope = scope->outer_scope();
1385   }
1386   return scope->AsDeclarationScope();
1387 }
1388 
GetOuterScopeWithContext()1389 Scope* Scope::GetOuterScopeWithContext() {
1390   Scope* scope = outer_scope_;
1391   while (scope && !scope->NeedsContext()) {
1392     scope = scope->outer_scope();
1393   }
1394   return scope;
1395 }
1396 
1397 namespace {
WasLazilyParsed(Scope * scope)1398 bool WasLazilyParsed(Scope* scope) {
1399   return scope->is_declaration_scope() &&
1400          scope->AsDeclarationScope()->was_lazily_parsed();
1401 }
1402 
1403 }  // namespace
1404 
1405 template <typename FunctionType>
ForEach(FunctionType callback)1406 void Scope::ForEach(FunctionType callback) {
1407   Scope* scope = this;
1408   while (true) {
1409     Iteration iteration = callback(scope);
1410     // Try to descend into inner scopes first.
1411     if ((iteration == Iteration::kDescend) && scope->inner_scope_ != nullptr) {
1412       scope = scope->inner_scope_;
1413     } else {
1414       // Find the next outer scope with a sibling.
1415       while (scope->sibling_ == nullptr) {
1416         if (scope == this) return;
1417         scope = scope->outer_scope_;
1418       }
1419       if (scope == this) return;
1420       scope = scope->sibling_;
1421     }
1422   }
1423 }
1424 
IsOuterScopeOf(Scope * other) const1425 bool Scope::IsOuterScopeOf(Scope* other) const {
1426   Scope* scope = other;
1427   while (scope) {
1428     if (scope == this) return true;
1429     scope = scope->outer_scope();
1430   }
1431   return false;
1432 }
1433 
CollectNonLocals(DeclarationScope * max_outer_scope,Isolate * isolate,Handle<StringSet> * non_locals)1434 void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1435                              Isolate* isolate, Handle<StringSet>* non_locals) {
1436   this->ForEach([max_outer_scope, isolate, non_locals](Scope* scope) {
1437     // Module variables must be allocated before variable resolution
1438     // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1439     if (scope->is_module_scope()) {
1440       scope->AsModuleScope()->AllocateModuleVariables();
1441     }
1442 
1443     // Lazy parsed declaration scopes are already partially analyzed. If there
1444     // are unresolved references remaining, they just need to be resolved in
1445     // outer scopes.
1446     Scope* lookup = WasLazilyParsed(scope) ? scope->outer_scope() : scope;
1447 
1448     for (VariableProxy* proxy : scope->unresolved_list_) {
1449       DCHECK(!proxy->is_resolved());
1450       Variable* var =
1451           Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1452       if (var == nullptr) {
1453         *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1454       } else {
1455         // In this case we need to leave scopes in a way that they can be
1456         // allocated. If we resolved variables from lazy parsed scopes, we need
1457         // to context allocate the var.
1458         scope->ResolveTo(proxy, var);
1459         if (!var->is_dynamic() && lookup != scope)
1460           var->ForceContextAllocation();
1461       }
1462     }
1463 
1464     // Clear unresolved_list_ as it's in an inconsistent state.
1465     scope->unresolved_list_.Clear();
1466     return Iteration::kDescend;
1467   });
1468 }
1469 
AnalyzePartially(DeclarationScope * max_outer_scope,AstNodeFactory * ast_node_factory,UnresolvedList * new_unresolved_list,bool maybe_in_arrowhead)1470 void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1471                              AstNodeFactory* ast_node_factory,
1472                              UnresolvedList* new_unresolved_list,
1473                              bool maybe_in_arrowhead) {
1474   this->ForEach([max_outer_scope, ast_node_factory, new_unresolved_list,
1475                  maybe_in_arrowhead](Scope* scope) {
1476     DCHECK_IMPLIES(scope->is_declaration_scope(),
1477                    !scope->AsDeclarationScope()->was_lazily_parsed());
1478 
1479     for (VariableProxy* proxy = scope->unresolved_list_.first();
1480          proxy != nullptr; proxy = proxy->next_unresolved()) {
1481       if (proxy->is_removed_from_unresolved()) continue;
1482       DCHECK(!proxy->is_resolved());
1483       Variable* var =
1484           Lookup<kParsedScope>(proxy, scope, max_outer_scope->outer_scope());
1485       if (var == nullptr) {
1486         // Don't copy unresolved references to the script scope, unless it's a
1487         // reference to a private name or method. In that case keep it so we
1488         // can fail later.
1489         if (!max_outer_scope->outer_scope()->is_script_scope() ||
1490             maybe_in_arrowhead) {
1491           VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1492           new_unresolved_list->Add(copy);
1493         }
1494       } else {
1495         var->set_is_used();
1496         if (proxy->is_assigned()) var->SetMaybeAssigned();
1497       }
1498     }
1499 
1500     // Clear unresolved_list_ as it's in an inconsistent state.
1501     scope->unresolved_list_.Clear();
1502     return Iteration::kDescend;
1503   });
1504 }
1505 
CollectNonLocals(Isolate * isolate,Handle<StringSet> non_locals)1506 Handle<StringSet> DeclarationScope::CollectNonLocals(
1507     Isolate* isolate, Handle<StringSet> non_locals) {
1508   Scope::CollectNonLocals(this, isolate, &non_locals);
1509   return non_locals;
1510 }
1511 
ResetAfterPreparsing(AstValueFactory * ast_value_factory,bool aborted)1512 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1513                                             bool aborted) {
1514   DCHECK(is_function_scope());
1515 
1516   // Reset all non-trivial members.
1517   params_.DropAndClear();
1518   decls_.Clear();
1519   locals_.Clear();
1520   inner_scope_ = nullptr;
1521   unresolved_list_.Clear();
1522   sloppy_block_functions_.Clear();
1523   rare_data_ = nullptr;
1524   has_rest_ = false;
1525   function_ = nullptr;
1526 
1527   DCHECK_NE(zone(), ast_value_factory->zone());
1528   // Make sure this scope and zone aren't used for allocation anymore.
1529   {
1530     // Get the zone, while variables_ is still valid
1531     Zone* zone = this->zone();
1532     variables_.Invalidate();
1533     zone->ReleaseMemory();
1534   }
1535 
1536   if (aborted) {
1537     // Prepare scope for use in the outer zone.
1538     variables_ = VariableMap(ast_value_factory->zone());
1539     if (!IsArrowFunction(function_kind_)) {
1540       has_simple_parameters_ = true;
1541       DeclareDefaultFunctionVariables(ast_value_factory);
1542     }
1543   }
1544 
1545 #ifdef DEBUG
1546   needs_migration_ = false;
1547   is_being_lazily_parsed_ = false;
1548 #endif
1549 
1550   was_lazily_parsed_ = !aborted;
1551 }
1552 
IsSkippableFunctionScope()1553 bool Scope::IsSkippableFunctionScope() {
1554   // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
1555   // those Scopes which have their own PreparseDataBuilder object. This
1556   // logic ensures that the scope allocation data is consistent with the
1557   // skippable function data (both agree on where the lazy function boundaries
1558   // are).
1559   if (!is_function_scope()) return false;
1560   DeclarationScope* declaration_scope = AsDeclarationScope();
1561   return !declaration_scope->is_arrow_scope() &&
1562          declaration_scope->preparse_data_builder() != nullptr;
1563 }
1564 
SavePreparseData(Parser * parser)1565 void Scope::SavePreparseData(Parser* parser) {
1566   this->ForEach([parser](Scope* scope) {
1567     if (scope->IsSkippableFunctionScope()) {
1568       scope->AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
1569     }
1570     return Iteration::kDescend;
1571   });
1572 }
1573 
SavePreparseDataForDeclarationScope(Parser * parser)1574 void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
1575   if (preparse_data_builder_ == nullptr) return;
1576   preparse_data_builder_->SaveScopeAllocationData(this, parser);
1577 }
1578 
AnalyzePartially(Parser * parser,AstNodeFactory * ast_node_factory,bool maybe_in_arrowhead)1579 void DeclarationScope::AnalyzePartially(Parser* parser,
1580                                         AstNodeFactory* ast_node_factory,
1581                                         bool maybe_in_arrowhead) {
1582   DCHECK(!force_eager_compilation_);
1583   UnresolvedList new_unresolved_list;
1584   if (!IsArrowFunction(function_kind_) &&
1585       (!outer_scope_->is_script_scope() || maybe_in_arrowhead ||
1586        (preparse_data_builder_ != nullptr &&
1587         preparse_data_builder_->HasInnerFunctions()))) {
1588     // Try to resolve unresolved variables for this Scope and migrate those
1589     // which cannot be resolved inside. It doesn't make sense to try to resolve
1590     // them in the outer Scopes here, because they are incomplete.
1591     Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list,
1592                             maybe_in_arrowhead);
1593 
1594     // Migrate function_ to the right Zone.
1595     if (function_ != nullptr) {
1596       function_ = ast_node_factory->CopyVariable(function_);
1597     }
1598 
1599     SavePreparseData(parser);
1600   }
1601 
1602 #ifdef DEBUG
1603   if (FLAG_print_scopes) {
1604     PrintF("Inner function scope:\n");
1605     Print();
1606   }
1607 #endif
1608 
1609   ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1610 
1611   unresolved_list_ = std::move(new_unresolved_list);
1612 }
1613 
RewriteReplGlobalVariables()1614 void DeclarationScope::RewriteReplGlobalVariables() {
1615   DCHECK(is_script_scope());
1616   if (!is_repl_mode_scope()) return;
1617 
1618   for (VariableMap::Entry* p = variables_.Start(); p != nullptr;
1619        p = variables_.Next(p)) {
1620     Variable* var = reinterpret_cast<Variable*>(p->value);
1621     var->RewriteLocationForRepl();
1622   }
1623 }
1624 
1625 #ifdef DEBUG
1626 namespace {
1627 
Header(ScopeType scope_type,FunctionKind function_kind,bool is_declaration_scope)1628 const char* Header(ScopeType scope_type, FunctionKind function_kind,
1629                    bool is_declaration_scope) {
1630   switch (scope_type) {
1631     case EVAL_SCOPE: return "eval";
1632     case FUNCTION_SCOPE:
1633       if (IsGeneratorFunction(function_kind)) return "function*";
1634       if (IsAsyncFunction(function_kind)) return "async function";
1635       if (IsArrowFunction(function_kind)) return "arrow";
1636       return "function";
1637     case MODULE_SCOPE: return "module";
1638     case SCRIPT_SCOPE: return "global";
1639     case CATCH_SCOPE: return "catch";
1640     case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1641     case CLASS_SCOPE:
1642       return "class";
1643     case WITH_SCOPE: return "with";
1644   }
1645   UNREACHABLE();
1646 }
1647 
Indent(int n,const char * str)1648 void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1649 
PrintName(const AstRawString * name)1650 void PrintName(const AstRawString* name) {
1651   PrintF("%.*s", name->length(), name->raw_data());
1652 }
1653 
PrintLocation(Variable * var)1654 void PrintLocation(Variable* var) {
1655   switch (var->location()) {
1656     case VariableLocation::UNALLOCATED:
1657       break;
1658     case VariableLocation::PARAMETER:
1659       PrintF("parameter[%d]", var->index());
1660       break;
1661     case VariableLocation::LOCAL:
1662       PrintF("local[%d]", var->index());
1663       break;
1664     case VariableLocation::CONTEXT:
1665       PrintF("context[%d]", var->index());
1666       break;
1667     case VariableLocation::LOOKUP:
1668       PrintF("lookup");
1669       break;
1670     case VariableLocation::MODULE:
1671       PrintF("module");
1672       break;
1673     case VariableLocation::REPL_GLOBAL:
1674       PrintF("repl global[%d]", var->index());
1675       break;
1676   }
1677 }
1678 
PrintVar(int indent,Variable * var)1679 void PrintVar(int indent, Variable* var) {
1680   Indent(indent, VariableMode2String(var->mode()));
1681   PrintF(" ");
1682   if (var->raw_name()->IsEmpty())
1683     PrintF(".%p", reinterpret_cast<void*>(var));
1684   else
1685     PrintName(var->raw_name());
1686   PrintF(";  // (%p) ", reinterpret_cast<void*>(var));
1687   PrintLocation(var);
1688   bool comma = !var->IsUnallocated();
1689   if (var->has_forced_context_allocation()) {
1690     if (comma) PrintF(", ");
1691     PrintF("forced context allocation");
1692     comma = true;
1693   }
1694   if (var->maybe_assigned() == kNotAssigned) {
1695     if (comma) PrintF(", ");
1696     PrintF("never assigned");
1697     comma = true;
1698   }
1699   if (var->initialization_flag() == kNeedsInitialization &&
1700       !var->binding_needs_init()) {
1701     if (comma) PrintF(", ");
1702     PrintF("hole initialization elided");
1703   }
1704   PrintF("\n");
1705 }
1706 
PrintMap(int indent,const char * label,VariableMap * map,bool locals,Variable * function_var)1707 void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1708               Variable* function_var) {
1709   bool printed_label = false;
1710   for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1711     Variable* var = reinterpret_cast<Variable*>(p->value);
1712     if (var == function_var) continue;
1713     bool local = !IsDynamicVariableMode(var->mode());
1714     if ((locals ? local : !local) &&
1715         (var->is_used() || !var->IsUnallocated())) {
1716       if (!printed_label) {
1717         Indent(indent, label);
1718         printed_label = true;
1719       }
1720       PrintVar(indent, var);
1721     }
1722   }
1723 }
1724 
1725 }  // anonymous namespace
1726 
PrintParameters()1727 void DeclarationScope::PrintParameters() {
1728   PrintF(" (");
1729   for (int i = 0; i < params_.length(); i++) {
1730     if (i > 0) PrintF(", ");
1731     const AstRawString* name = params_[i]->raw_name();
1732     if (name->IsEmpty()) {
1733       PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1734     } else {
1735       PrintName(name);
1736     }
1737   }
1738   PrintF(")");
1739 }
1740 
Print(int n)1741 void Scope::Print(int n) {
1742   int n0 = (n > 0 ? n : 0);
1743   int n1 = n0 + 2;  // indentation
1744 
1745   // Print header.
1746   FunctionKind function_kind = is_function_scope()
1747                                    ? AsDeclarationScope()->function_kind()
1748                                    : kNormalFunction;
1749   Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1750   if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1751     PrintF(" ");
1752     PrintName(scope_name_);
1753   }
1754 
1755   // Print parameters, if any.
1756   Variable* function = nullptr;
1757   if (is_function_scope()) {
1758     AsDeclarationScope()->PrintParameters();
1759     function = AsDeclarationScope()->function_var();
1760   }
1761 
1762   PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
1763          start_position(), end_position());
1764   if (is_hidden()) {
1765     Indent(n1, "// is hidden\n");
1766   }
1767 
1768   // Function name, if any (named function literals, only).
1769   if (function != nullptr) {
1770     Indent(n1, "// (local) function name: ");
1771     PrintName(function->raw_name());
1772     PrintF("\n");
1773   }
1774 
1775   // Scope info.
1776   if (is_strict(language_mode())) {
1777     Indent(n1, "// strict mode scope\n");
1778   }
1779   if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1780   if (is_declaration_scope() &&
1781       AsDeclarationScope()->sloppy_eval_can_extend_vars()) {
1782     Indent(n1, "// scope calls sloppy 'eval'\n");
1783   }
1784   if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) {
1785     Indent(n1, "// scope needs home object\n");
1786   }
1787   if (private_name_lookup_skips_outer_class()) {
1788     Indent(n1, "// scope skips outer class for #-names\n");
1789   }
1790   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1791   if (is_declaration_scope()) {
1792     DeclarationScope* scope = AsDeclarationScope();
1793     if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1794     if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1795     if (scope->needs_private_name_context_chain_recalc()) {
1796       Indent(n1, "// needs #-name context chain recalc\n");
1797     }
1798   }
1799   if (num_stack_slots_ > 0) {
1800     Indent(n1, "// ");
1801     PrintF("%d stack slots\n", num_stack_slots_);
1802   }
1803   if (num_heap_slots_ > 0) {
1804     Indent(n1, "// ");
1805     PrintF("%d heap slots\n", num_heap_slots_);
1806   }
1807 
1808   // Print locals.
1809   if (function != nullptr) {
1810     Indent(n1, "// function var:\n");
1811     PrintVar(n1, function);
1812   }
1813 
1814   // Print temporaries.
1815   {
1816     bool printed_header = false;
1817     for (Variable* local : locals_) {
1818       if (local->mode() != VariableMode::kTemporary) continue;
1819       if (!printed_header) {
1820         printed_header = true;
1821         Indent(n1, "// temporary vars:\n");
1822       }
1823       PrintVar(n1, local);
1824     }
1825   }
1826 
1827   if (variables_.occupancy() > 0) {
1828     PrintMap(n1, "// local vars:\n", &variables_, true, function);
1829     PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1830   }
1831 
1832   if (is_class_scope()) {
1833     ClassScope* class_scope = AsClassScope();
1834     if (class_scope->GetRareData() != nullptr) {
1835       PrintMap(n1, "// private name vars:\n",
1836                &(class_scope->GetRareData()->private_name_map), true, function);
1837       Variable* brand = class_scope->brand();
1838       if (brand != nullptr) {
1839         Indent(n1, "// brand var:\n");
1840         PrintVar(n1, brand);
1841       }
1842     }
1843     if (class_scope->class_variable() != nullptr) {
1844       Indent(n1, "// class var");
1845       PrintF("%s%s:\n",
1846              class_scope->class_variable()->is_used() ? ", used" : ", unused",
1847              class_scope->should_save_class_variable_index()
1848                  ? ", index saved"
1849                  : ", index not saved");
1850       PrintVar(n1, class_scope->class_variable());
1851     }
1852   }
1853 
1854   // Print inner scopes (disable by providing negative n).
1855   if (n >= 0) {
1856     for (Scope* scope = inner_scope_; scope != nullptr;
1857          scope = scope->sibling_) {
1858       PrintF("\n");
1859       scope->Print(n1);
1860     }
1861   }
1862 
1863   Indent(n0, "}\n");
1864 }
1865 
CheckScopePositions()1866 void Scope::CheckScopePositions() {
1867   this->ForEach([](Scope* scope) {
1868     // Visible leaf scopes must have real positions.
1869     if (!scope->is_hidden() && scope->inner_scope_ == nullptr) {
1870       DCHECK_NE(kNoSourcePosition, scope->start_position());
1871       DCHECK_NE(kNoSourcePosition, scope->end_position());
1872     }
1873     return Iteration::kDescend;
1874   });
1875 }
1876 
CheckZones()1877 void Scope::CheckZones() {
1878   DCHECK(!needs_migration_);
1879   this->ForEach([](Scope* scope) {
1880     if (WasLazilyParsed(scope)) {
1881       DCHECK_NULL(scope->zone());
1882       DCHECK_NULL(scope->inner_scope_);
1883       return Iteration::kContinue;
1884     }
1885     return Iteration::kDescend;
1886   });
1887 }
1888 #endif  // DEBUG
1889 
NonLocal(const AstRawString * name,VariableMode mode)1890 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1891   // Declare a new non-local.
1892   DCHECK(IsDynamicVariableMode(mode));
1893   bool was_added;
1894   Variable* var = variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
1895                                      kCreatedInitialized, kNotAssigned,
1896                                      IsStaticFlag::kNotStatic, &was_added);
1897   // Allocate it by giving it a dynamic lookup.
1898   var->AllocateTo(VariableLocation::LOOKUP, -1);
1899   return var;
1900 }
1901 
1902 // static
1903 template <Scope::ScopeLookupMode mode>
Lookup(VariableProxy * proxy,Scope * scope,Scope * outer_scope_end,Scope * cache_scope,bool force_context_allocation)1904 Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
1905                         Scope* outer_scope_end, Scope* cache_scope,
1906                         bool force_context_allocation) {
1907   // If we have already passed the cache scope in earlier recursions, we should
1908   // first quickly check if the current scope uses the cache scope before
1909   // continuing.
1910   if (mode == kDeserializedScope &&
1911       scope->deserialized_scope_uses_external_cache()) {
1912     Variable* var = cache_scope->variables_.Lookup(proxy->raw_name());
1913     if (var != nullptr) return var;
1914   }
1915 
1916   while (true) {
1917     DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
1918     // Short-cut: whenever we find a debug-evaluate scope, just look everything
1919     // up dynamically. Debug-evaluate doesn't properly create scope info for the
1920     // lookups it does. It may not have a valid 'this' declaration, and anything
1921     // accessed through debug-evaluate might invalidly resolve to
1922     // stack-allocated variables.
1923     // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
1924     // the scopes in which it's evaluating.
1925     if (mode == kDeserializedScope &&
1926         V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
1927       DCHECK(scope->deserialized_scope_uses_external_cache() ||
1928              scope == cache_scope);
1929       return cache_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1930     }
1931 
1932     // Try to find the variable in this scope.
1933     Variable* var;
1934     if (mode == kParsedScope) {
1935       var = scope->LookupLocal(proxy->raw_name());
1936     } else {
1937       DCHECK_EQ(mode, kDeserializedScope);
1938       bool external_cache = scope->deserialized_scope_uses_external_cache();
1939       if (!external_cache) {
1940         // Check the cache on each deserialized scope, up to the main cache
1941         // scope when we get to it (we may still have deserialized scopes
1942         // in-between the initial and cache scopes so we can't just check the
1943         // cache before the loop).
1944         Variable* var = scope->variables_.Lookup(proxy->raw_name());
1945         if (var != nullptr) return var;
1946       }
1947       var = scope->LookupInScopeInfo(proxy->raw_name(),
1948                                      external_cache ? cache_scope : scope);
1949     }
1950 
1951     // We found a variable and we are done. (Even if there is an 'eval' in this
1952     // scope which introduces the same variable again, the resulting variable
1953     // remains the same.)
1954     //
1955     // For sloppy eval though, we skip dynamic variable to avoid resolving to a
1956     // variable when the variable and proxy are in the same eval execution. The
1957     // variable is not available on subsequent lazy executions of functions in
1958     // the eval, so this avoids inner functions from looking up different
1959     // variables during eager and lazy compilation.
1960     //
1961     // TODO(leszeks): Maybe we want to restrict this to e.g. lookups of a proxy
1962     // living in a different scope to the current one, or some other
1963     // optimisation.
1964     if (var != nullptr &&
1965         !(scope->is_eval_scope() && var->mode() == VariableMode::kDynamic)) {
1966       if (mode == kParsedScope && force_context_allocation &&
1967           !var->is_dynamic()) {
1968         var->ForceContextAllocation();
1969       }
1970       return var;
1971     }
1972 
1973     if (scope->outer_scope_ == outer_scope_end) break;
1974 
1975     DCHECK(!scope->is_script_scope());
1976     if (V8_UNLIKELY(scope->is_with_scope())) {
1977       return LookupWith(proxy, scope, outer_scope_end, cache_scope,
1978                         force_context_allocation);
1979     }
1980     if (V8_UNLIKELY(
1981             scope->is_declaration_scope() &&
1982             scope->AsDeclarationScope()->sloppy_eval_can_extend_vars())) {
1983       return LookupSloppyEval(proxy, scope, outer_scope_end, cache_scope,
1984                               force_context_allocation);
1985     }
1986 
1987     force_context_allocation |= scope->is_function_scope();
1988     scope = scope->outer_scope_;
1989 
1990     // TODO(verwaest): Separate through AnalyzePartially.
1991     if (mode == kParsedScope && !scope->scope_info_.is_null()) {
1992       DCHECK_NULL(cache_scope);
1993       Scope* cache_scope = scope->GetNonEvalDeclarationScope();
1994       return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end,
1995                                         cache_scope);
1996     }
1997   }
1998 
1999   // We may just be trying to find all free variables. In that case, don't
2000   // declare them in the outer scope.
2001   // TODO(marja): Separate Lookup for preparsed scopes better.
2002   if (mode == kParsedScope && !scope->is_script_scope()) {
2003     return nullptr;
2004   }
2005 
2006   // No binding has been found. Declare a variable on the global object.
2007   return scope->AsDeclarationScope()->DeclareDynamicGlobal(
2008       proxy->raw_name(), NORMAL_VARIABLE,
2009       mode == kDeserializedScope ? cache_scope : scope);
2010 }
2011 
2012 template Variable* Scope::Lookup<Scope::kParsedScope>(
2013     VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
2014     Scope* cache_scope, bool force_context_allocation);
2015 template Variable* Scope::Lookup<Scope::kDeserializedScope>(
2016     VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
2017     Scope* cache_scope, bool force_context_allocation);
2018 
LookupWith(VariableProxy * proxy,Scope * scope,Scope * outer_scope_end,Scope * cache_scope,bool force_context_allocation)2019 Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
2020                             Scope* outer_scope_end, Scope* cache_scope,
2021                             bool force_context_allocation) {
2022   DCHECK(scope->is_with_scope());
2023 
2024   Variable* var =
2025       scope->outer_scope_->scope_info_.is_null()
2026           ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
2027                                  nullptr, force_context_allocation)
2028           : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
2029                                        outer_scope_end, cache_scope);
2030 
2031   if (var == nullptr) return var;
2032 
2033   // The current scope is a with scope, so the variable binding can not be
2034   // statically resolved. However, note that it was necessary to do a lookup
2035   // in the outer scope anyway, because if a binding exists in an outer
2036   // scope, the associated variable has to be marked as potentially being
2037   // accessed from inside of an inner with scope (the property may not be in
2038   // the 'with' object).
2039   if (!var->is_dynamic() && var->IsUnallocated()) {
2040     DCHECK(!scope->already_resolved_);
2041     var->set_is_used();
2042     var->ForceContextAllocation();
2043     if (proxy->is_assigned()) var->SetMaybeAssigned();
2044   }
2045   Scope* target_scope;
2046   if (scope->deserialized_scope_uses_external_cache()) {
2047     DCHECK_NOT_NULL(cache_scope);
2048     cache_scope->variables_.Remove(var);
2049     target_scope = cache_scope;
2050   } else {
2051     target_scope = scope;
2052   }
2053   Variable* dynamic =
2054       target_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
2055   dynamic->set_local_if_not_shadowed(var);
2056   return dynamic;
2057 }
2058 
LookupSloppyEval(VariableProxy * proxy,Scope * scope,Scope * outer_scope_end,Scope * cache_scope,bool force_context_allocation)2059 Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
2060                                   Scope* outer_scope_end, Scope* cache_scope,
2061                                   bool force_context_allocation) {
2062   DCHECK(scope->is_declaration_scope() &&
2063          scope->AsDeclarationScope()->sloppy_eval_can_extend_vars());
2064 
2065   // If we're compiling eval, it's possible that the outer scope is the first
2066   // ScopeInfo-backed scope. We use the next declaration scope as the cache for
2067   // this case, to avoid complexity around sloppy block function hoisting and
2068   // conflict detection through catch scopes in the eval.
2069   Scope* entry_cache = cache_scope == nullptr
2070                            ? scope->outer_scope()->GetNonEvalDeclarationScope()
2071                            : cache_scope;
2072   Variable* var =
2073       scope->outer_scope_->scope_info_.is_null()
2074           ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
2075                                  nullptr, force_context_allocation)
2076           : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
2077                                        outer_scope_end, entry_cache);
2078   if (var == nullptr) return var;
2079 
2080   // We may not want to use the cache scope, change it back to the given scope
2081   // if necessary.
2082   if (!scope->deserialized_scope_uses_external_cache()) {
2083     // For a deserialized scope, we'll be replacing the cache_scope.
2084     DCHECK_IMPLIES(!scope->scope_info_.is_null(), cache_scope != nullptr);
2085     cache_scope = scope;
2086   }
2087 
2088   // A variable binding may have been found in an outer scope, but the current
2089   // scope makes a sloppy 'eval' call, so the found variable may not be the
2090   // correct one (the 'eval' may introduce a binding with the same name). In
2091   // that case, change the lookup result to reflect this situation. Only
2092   // scopes that can host var bindings (declaration scopes) need be considered
2093   // here (this excludes block and catch scopes), and variable lookups at
2094   // script scope are always dynamic.
2095   if (var->IsGlobalObjectProperty()) {
2096     Scope* target = cache_scope == nullptr ? scope : cache_scope;
2097     var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
2098   }
2099 
2100   if (var->is_dynamic()) return var;
2101 
2102   Variable* invalidated = var;
2103   if (cache_scope != nullptr) cache_scope->variables_.Remove(invalidated);
2104 
2105   Scope* target = cache_scope == nullptr ? scope : cache_scope;
2106   var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
2107   var->set_local_if_not_shadowed(invalidated);
2108 
2109   return var;
2110 }
2111 
ResolveVariable(VariableProxy * proxy)2112 void Scope::ResolveVariable(VariableProxy* proxy) {
2113   DCHECK(!proxy->is_resolved());
2114   Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
2115   DCHECK_NOT_NULL(var);
2116   ResolveTo(proxy, var);
2117 }
2118 
2119 namespace {
2120 
SetNeedsHoleCheck(Variable * var,VariableProxy * proxy)2121 void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
2122   proxy->set_needs_hole_check();
2123   var->ForceHoleInitialization();
2124 }
2125 
UpdateNeedsHoleCheck(Variable * var,VariableProxy * proxy,Scope * scope)2126 void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
2127   if (var->mode() == VariableMode::kDynamicLocal) {
2128     // Dynamically introduced variables never need a hole check (since they're
2129     // VariableMode::kVar bindings, either from var or function declarations),
2130     // but the variable they shadow might need a hole check, which we want to do
2131     // if we decide that no shadowing variable was dynamically introoduced.
2132     DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
2133     return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
2134   }
2135 
2136   if (var->initialization_flag() == kCreatedInitialized) return;
2137 
2138   // It's impossible to eliminate module import hole checks here, because it's
2139   // unknown at compilation time whether the binding referred to in the
2140   // exporting module itself requires hole checks.
2141   if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
2142     return SetNeedsHoleCheck(var, proxy);
2143   }
2144 
2145   // Check if the binding really needs an initialization check. The check
2146   // can be skipped in the following situation: we have a VariableMode::kLet or
2147   // VariableMode::kConst binding, both the Variable and the VariableProxy have
2148   // the same declaration scope (i.e. they are both in global code, in the same
2149   // function or in the same eval code), the VariableProxy is in the source
2150   // physically located after the initializer of the variable, and that the
2151   // initializer cannot be skipped due to a nonlinear scope.
2152   //
2153   // The condition on the closure scopes is a conservative check for
2154   // nested functions that access a binding and are called before the
2155   // binding is initialized:
2156   //   function() { f(); let x = 1; function f() { x = 2; } }
2157   //
2158   // The check cannot be skipped on non-linear scopes, namely switch
2159   // scopes, to ensure tests are done in cases like the following:
2160   //   switch (1) { case 0: let x = 2; case 1: f(x); }
2161   // The scope of the variable needs to be checked, in case the use is
2162   // in a sub-block which may be linear.
2163   if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
2164     return SetNeedsHoleCheck(var, proxy);
2165   }
2166 
2167   // We should always have valid source positions.
2168   DCHECK_NE(var->initializer_position(), kNoSourcePosition);
2169   DCHECK_NE(proxy->position(), kNoSourcePosition);
2170 
2171   if (var->scope()->is_nonlinear() ||
2172       var->initializer_position() >= proxy->position()) {
2173     return SetNeedsHoleCheck(var, proxy);
2174   }
2175 }
2176 
2177 }  // anonymous namespace
2178 
ResolveTo(VariableProxy * proxy,Variable * var)2179 void Scope::ResolveTo(VariableProxy* proxy, Variable* var) {
2180   DCHECK_NOT_NULL(var);
2181   UpdateNeedsHoleCheck(var, proxy, this);
2182   proxy->BindTo(var);
2183 }
2184 
ResolvePreparsedVariable(VariableProxy * proxy,Scope * scope,Scope * end)2185 void Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
2186                                      Scope* end) {
2187   // Resolve the variable in all parsed scopes to force context allocation.
2188   for (; scope != end; scope = scope->outer_scope_) {
2189     Variable* var = scope->LookupLocal(proxy->raw_name());
2190     if (var != nullptr) {
2191       var->set_is_used();
2192       if (!var->is_dynamic()) {
2193         var->ForceContextAllocation();
2194         if (proxy->is_assigned()) var->SetMaybeAssigned();
2195         return;
2196       }
2197     }
2198   }
2199 }
2200 
ResolveVariablesRecursively(Scope * end)2201 bool Scope::ResolveVariablesRecursively(Scope* end) {
2202   // Lazy parsed declaration scopes are already partially analyzed. If there are
2203   // unresolved references remaining, they just need to be resolved in outer
2204   // scopes.
2205   if (WasLazilyParsed(this)) {
2206     DCHECK_EQ(variables_.occupancy(), 0);
2207     // Resolve in all parsed scopes except for the script scope.
2208     if (!end->is_script_scope()) end = end->outer_scope();
2209 
2210     for (VariableProxy* proxy : unresolved_list_) {
2211       ResolvePreparsedVariable(proxy, outer_scope(), end);
2212     }
2213   } else {
2214     // Resolve unresolved variables for this scope.
2215     for (VariableProxy* proxy : unresolved_list_) {
2216       ResolveVariable(proxy);
2217     }
2218 
2219     // Resolve unresolved variables for inner scopes.
2220     for (Scope* scope = inner_scope_; scope != nullptr;
2221          scope = scope->sibling_) {
2222       if (!scope->ResolveVariablesRecursively(end)) return false;
2223     }
2224   }
2225   return true;
2226 }
2227 
MustAllocate(Variable * var)2228 bool Scope::MustAllocate(Variable* var) {
2229   DCHECK(var->location() != VariableLocation::MODULE);
2230   // Give var a read/write use if there is a chance it might be accessed
2231   // via an eval() call.  This is only possible if the variable has a
2232   // visible name.
2233   if (!var->raw_name()->IsEmpty() &&
2234       (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2235     var->set_is_used();
2236     if (inner_scope_calls_eval_ && !var->is_this()) var->SetMaybeAssigned();
2237   }
2238   DCHECK(!var->has_forced_context_allocation() || var->is_used());
2239   // Global variables do not need to be allocated.
2240   return !var->IsGlobalObjectProperty() && var->is_used();
2241 }
2242 
2243 
MustAllocateInContext(Variable * var)2244 bool Scope::MustAllocateInContext(Variable* var) {
2245   // If var is accessed from an inner scope, or if there is a possibility
2246   // that it might be accessed from the current or an inner scope (through
2247   // an eval() call or a runtime with lookup), it must be allocated in the
2248   // context.
2249   //
2250   // Temporary variables are always stack-allocated.  Catch-bound variables are
2251   // always context-allocated.
2252   VariableMode mode = var->mode();
2253   if (mode == VariableMode::kTemporary) return false;
2254   if (is_catch_scope()) return true;
2255   if (is_script_scope() || is_eval_scope()) {
2256     if (IsLexicalVariableMode(mode)) {
2257       return true;
2258     }
2259   }
2260   return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2261 }
2262 
AllocateStackSlot(Variable * var)2263 void Scope::AllocateStackSlot(Variable* var) {
2264   if (is_block_scope()) {
2265     outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2266   } else {
2267     var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2268   }
2269 }
2270 
2271 
AllocateHeapSlot(Variable * var)2272 void Scope::AllocateHeapSlot(Variable* var) {
2273   var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2274 }
2275 
AllocateParameterLocals()2276 void DeclarationScope::AllocateParameterLocals() {
2277   DCHECK(is_function_scope());
2278 
2279   bool has_mapped_arguments = false;
2280   if (arguments_ != nullptr) {
2281     DCHECK(!is_arrow_scope());
2282     if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2283       // 'arguments' is used and does not refer to a function
2284       // parameter of the same name. If the arguments object
2285       // aliases formal parameters, we conservatively allocate
2286       // them specially in the loop below.
2287       has_mapped_arguments =
2288           GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2289     } else {
2290       // 'arguments' is unused. Tell the code generator that it does not need to
2291       // allocate the arguments object by nulling out arguments_.
2292       arguments_ = nullptr;
2293     }
2294   }
2295 
2296   // The same parameter may occur multiple times in the parameters_ list.
2297   // If it does, and if it is not copied into the context object, it must
2298   // receive the highest parameter index for that parameter; thus iteration
2299   // order is relevant!
2300   for (int i = num_parameters() - 1; i >= 0; --i) {
2301     Variable* var = params_[i];
2302     DCHECK_NOT_NULL(var);
2303     DCHECK(!has_rest_ || var != rest_parameter());
2304     DCHECK_EQ(this, var->scope());
2305     if (has_mapped_arguments) {
2306       var->set_is_used();
2307       var->SetMaybeAssigned();
2308       var->ForceContextAllocation();
2309     }
2310     AllocateParameter(var, i);
2311   }
2312 }
2313 
AllocateParameter(Variable * var,int index)2314 void DeclarationScope::AllocateParameter(Variable* var, int index) {
2315   if (!MustAllocate(var)) return;
2316   if (has_forced_context_allocation_for_parameters() ||
2317       MustAllocateInContext(var)) {
2318     DCHECK(var->IsUnallocated() || var->IsContextSlot());
2319     if (var->IsUnallocated()) AllocateHeapSlot(var);
2320   } else {
2321     DCHECK(var->IsUnallocated() || var->IsParameter());
2322     if (var->IsUnallocated()) {
2323       var->AllocateTo(VariableLocation::PARAMETER, index);
2324     }
2325   }
2326 }
2327 
AllocateReceiver()2328 void DeclarationScope::AllocateReceiver() {
2329   if (!has_this_declaration()) return;
2330   DCHECK_NOT_NULL(receiver());
2331   DCHECK_EQ(receiver()->scope(), this);
2332   AllocateParameter(receiver(), -1);
2333 }
2334 
AllocateNonParameterLocal(Variable * var)2335 void Scope::AllocateNonParameterLocal(Variable* var) {
2336   DCHECK_EQ(var->scope(), this);
2337   if (var->IsUnallocated() && MustAllocate(var)) {
2338     if (MustAllocateInContext(var)) {
2339       AllocateHeapSlot(var);
2340       DCHECK_IMPLIES(is_catch_scope(),
2341                      var->index() == Context::THROWN_OBJECT_INDEX);
2342     } else {
2343       AllocateStackSlot(var);
2344     }
2345   }
2346 }
2347 
AllocateNonParameterLocalsAndDeclaredGlobals()2348 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2349   if (is_declaration_scope() && AsDeclarationScope()->is_arrow_scope()) {
2350     // In arrow functions, allocate non-temporaries first and then all the
2351     // temporaries to make the local variable ordering stable when reparsing to
2352     // collect source positions.
2353     for (Variable* local : locals_) {
2354       if (local->mode() != VariableMode::kTemporary)
2355         AllocateNonParameterLocal(local);
2356     }
2357 
2358     for (Variable* local : locals_) {
2359       if (local->mode() == VariableMode::kTemporary)
2360         AllocateNonParameterLocal(local);
2361     }
2362   } else {
2363     for (Variable* local : locals_) {
2364       AllocateNonParameterLocal(local);
2365     }
2366   }
2367 
2368   if (is_declaration_scope()) {
2369     AsDeclarationScope()->AllocateLocals();
2370   }
2371 }
2372 
AllocateLocals()2373 void DeclarationScope::AllocateLocals() {
2374   // For now, function_ must be allocated at the very end.  If it gets
2375   // allocated in the context, it must be the last slot in the context,
2376   // because of the current ScopeInfo implementation (see
2377   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2378   if (function_ != nullptr && MustAllocate(function_)) {
2379     AllocateNonParameterLocal(function_);
2380   } else {
2381     function_ = nullptr;
2382   }
2383 
2384   DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2385          !rest_parameter()->IsUnallocated());
2386 
2387   if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2388     new_target_ = nullptr;
2389   }
2390 
2391   NullifyRareVariableIf(RareVariable::kThisFunction,
2392                         [=](Variable* var) { return !MustAllocate(var); });
2393 }
2394 
AllocateModuleVariables()2395 void ModuleScope::AllocateModuleVariables() {
2396   for (const auto& it : module()->regular_imports()) {
2397     Variable* var = LookupLocal(it.first);
2398     var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2399     DCHECK(!var->IsExport());
2400   }
2401 
2402   for (const auto& it : module()->regular_exports()) {
2403     Variable* var = LookupLocal(it.first);
2404     var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2405     DCHECK(var->IsExport());
2406   }
2407 }
2408 
AllocateVariablesRecursively()2409 void Scope::AllocateVariablesRecursively() {
2410   this->ForEach([](Scope* scope) -> Iteration {
2411     DCHECK(!scope->already_resolved_);
2412     if (WasLazilyParsed(scope)) return Iteration::kContinue;
2413     DCHECK_EQ(scope->ContextHeaderLength(), scope->num_heap_slots_);
2414 
2415     // Allocate variables for this scope.
2416     // Parameters must be allocated first, if any.
2417     if (scope->is_declaration_scope()) {
2418       if (scope->is_function_scope()) {
2419         scope->AsDeclarationScope()->AllocateParameterLocals();
2420       }
2421       scope->AsDeclarationScope()->AllocateReceiver();
2422     }
2423     scope->AllocateNonParameterLocalsAndDeclaredGlobals();
2424 
2425     // Force allocation of a context for this scope if necessary. For a 'with'
2426     // scope and for a function scope that makes an 'eval' call we need a
2427     // context, even if no local variables were statically allocated in the
2428     // scope. Likewise for modules and function scopes representing asm.js
2429     // modules. Also force a context, if the scope is stricter than the outer
2430     // scope.
2431     bool must_have_context =
2432         scope->is_with_scope() || scope->is_module_scope() ||
2433         scope->IsAsmModule() || scope->ForceContextForLanguageMode() ||
2434         (scope->is_function_scope() &&
2435          scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) ||
2436         (scope->is_block_scope() && scope->is_declaration_scope() &&
2437          scope->AsDeclarationScope()->sloppy_eval_can_extend_vars());
2438 
2439     // If we didn't allocate any locals in the local context, then we only
2440     // need the minimal number of slots if we must have a context.
2441     if (scope->num_heap_slots_ == scope->ContextHeaderLength() &&
2442         !must_have_context) {
2443       scope->num_heap_slots_ = 0;
2444     }
2445 
2446     // Allocation done.
2447     DCHECK(scope->num_heap_slots_ == 0 ||
2448            scope->num_heap_slots_ >= scope->ContextHeaderLength());
2449     return Iteration::kDescend;
2450   });
2451 }
2452 
2453 template <typename LocalIsolate>
AllocateScopeInfosRecursively(LocalIsolate * isolate,MaybeHandle<ScopeInfo> outer_scope)2454 void Scope::AllocateScopeInfosRecursively(LocalIsolate* isolate,
2455                                           MaybeHandle<ScopeInfo> outer_scope) {
2456   DCHECK(scope_info_.is_null());
2457   MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2458 
2459   if (NeedsScopeInfo()) {
2460     scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2461     // The ScopeInfo chain should mirror the context chain, so we only link to
2462     // the next outer scope that needs a context.
2463     if (NeedsContext()) next_outer_scope = scope_info_;
2464   }
2465 
2466   // Allocate ScopeInfos for inner scopes.
2467   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2468     if (!scope->is_function_scope() ||
2469         scope->AsDeclarationScope()->ShouldEagerCompile()) {
2470       scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2471     }
2472   }
2473 }
2474 
2475 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
2476     AllocateScopeInfosRecursively<Isolate>(Isolate* isolate,
2477                                            MaybeHandle<ScopeInfo> outer_scope);
2478 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
2479     AllocateScopeInfosRecursively<LocalIsolate>(
2480         LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
2481 
RecalcPrivateNameContextChain()2482 void DeclarationScope::RecalcPrivateNameContextChain() {
2483   // The outermost scope in a class heritage expression is marked to skip the
2484   // class scope during private name resolution. It is possible, however, that
2485   // either the class scope won't require a Context and ScopeInfo, or the
2486   // outermost scope in the heritage position won't. Simply copying the bit from
2487   // full parse into the ScopeInfo will break lazy compilation. In the former
2488   // case the scope that is marked to skip its outer scope will incorrectly skip
2489   // a different class scope than the one we intended to skip. In the latter
2490   // case variables resolved through an inner scope will incorrectly check the
2491   // class scope since we lost the skip bit from the outermost heritage scope.
2492   //
2493   // This method fixes both cases by, in outermost to innermost order, copying
2494   // the value of the skip bit from outer scopes that don't require a Context.
2495   DCHECK(needs_private_name_context_chain_recalc_);
2496   this->ForEach([](Scope* scope) {
2497     Scope* outer = scope->outer_scope();
2498     if (!outer) return Iteration::kDescend;
2499     if (!outer->NeedsContext()) {
2500       scope->private_name_lookup_skips_outer_class_ =
2501           outer->private_name_lookup_skips_outer_class();
2502     }
2503     if (!scope->is_function_scope() ||
2504         scope->AsDeclarationScope()->ShouldEagerCompile()) {
2505       return Iteration::kDescend;
2506     }
2507     return Iteration::kContinue;
2508   });
2509 }
2510 
RecordNeedsPrivateNameContextChainRecalc()2511 void DeclarationScope::RecordNeedsPrivateNameContextChainRecalc() {
2512   DCHECK_EQ(GetClosureScope(), this);
2513   DeclarationScope* scope;
2514   for (scope = this; scope != nullptr;
2515        scope = scope->outer_scope() != nullptr
2516                    ? scope->outer_scope()->GetClosureScope()
2517                    : nullptr) {
2518     if (scope->needs_private_name_context_chain_recalc_) return;
2519     scope->needs_private_name_context_chain_recalc_ = true;
2520   }
2521 }
2522 
2523 // static
2524 template <typename LocalIsolate>
AllocateScopeInfos(ParseInfo * info,LocalIsolate * isolate)2525 void DeclarationScope::AllocateScopeInfos(ParseInfo* info,
2526                                           LocalIsolate* isolate) {
2527   DeclarationScope* scope = info->literal()->scope();
2528 
2529   // No one else should have allocated a scope info for this scope yet.
2530   DCHECK(scope->scope_info_.is_null());
2531 
2532   MaybeHandle<ScopeInfo> outer_scope;
2533   if (scope->outer_scope_ != nullptr) {
2534     DCHECK((std::is_same<Isolate, v8::internal::Isolate>::value));
2535     outer_scope = scope->outer_scope_->scope_info_;
2536   }
2537 
2538   if (scope->needs_private_name_context_chain_recalc()) {
2539     scope->RecalcPrivateNameContextChain();
2540   }
2541   scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2542 
2543   // The debugger expects all shared function infos to contain a scope info.
2544   // Since the top-most scope will end up in a shared function info, make sure
2545   // it has one, even if it doesn't need a scope info.
2546   // TODO(jochen|yangguo): Remove this requirement.
2547   if (scope->scope_info_.is_null()) {
2548     scope->scope_info_ =
2549         ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2550   }
2551 
2552   // Ensuring that the outer script scope has a scope info avoids having
2553   // special case for native contexts vs other contexts.
2554   if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2555     info->script_scope()->scope_info_ = isolate->factory()->empty_scope_info();
2556   }
2557 }
2558 
2559 template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
2560     ParseInfo* info, Isolate* isolate);
2561 template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
2562     ParseInfo* info, LocalIsolate* isolate);
2563 
ContextLocalCount() const2564 int Scope::ContextLocalCount() const {
2565   if (num_heap_slots() == 0) return 0;
2566   Variable* function =
2567       is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2568   bool is_function_var_in_context =
2569       function != nullptr && function->IsContextSlot();
2570   return num_heap_slots() - ContextHeaderLength() -
2571          (is_function_var_in_context ? 1 : 0);
2572 }
2573 
IsComplementaryAccessorPair(VariableMode a,VariableMode b)2574 bool IsComplementaryAccessorPair(VariableMode a, VariableMode b) {
2575   switch (a) {
2576     case VariableMode::kPrivateGetterOnly:
2577       return b == VariableMode::kPrivateSetterOnly;
2578     case VariableMode::kPrivateSetterOnly:
2579       return b == VariableMode::kPrivateGetterOnly;
2580     default:
2581       return false;
2582   }
2583 }
2584 
DeclarePrivateName(const AstRawString * name,VariableMode mode,IsStaticFlag is_static_flag,bool * was_added)2585 Variable* ClassScope::DeclarePrivateName(const AstRawString* name,
2586                                          VariableMode mode,
2587                                          IsStaticFlag is_static_flag,
2588                                          bool* was_added) {
2589   Variable* result = EnsureRareData()->private_name_map.Declare(
2590       zone(), this, name, mode, NORMAL_VARIABLE,
2591       InitializationFlag::kNeedsInitialization, MaybeAssignedFlag::kNotAssigned,
2592       is_static_flag, was_added);
2593   if (*was_added) {
2594     locals_.Add(result);
2595     has_static_private_methods_ |=
2596         (result->is_static() &&
2597          IsPrivateMethodOrAccessorVariableMode(result->mode()));
2598   } else if (IsComplementaryAccessorPair(result->mode(), mode) &&
2599              result->is_static_flag() == is_static_flag) {
2600     *was_added = true;
2601     result->set_mode(VariableMode::kPrivateGetterAndSetter);
2602   }
2603   result->ForceContextAllocation();
2604   return result;
2605 }
2606 
LookupLocalPrivateName(const AstRawString * name)2607 Variable* ClassScope::LookupLocalPrivateName(const AstRawString* name) {
2608   RareData* rare_data = GetRareData();
2609   if (rare_data == nullptr) {
2610     return nullptr;
2611   }
2612   return rare_data->private_name_map.Lookup(name);
2613 }
2614 
GetUnresolvedPrivateNameTail()2615 UnresolvedList::Iterator ClassScope::GetUnresolvedPrivateNameTail() {
2616   RareData* rare_data = GetRareData();
2617   if (rare_data == nullptr) {
2618     return UnresolvedList::Iterator();
2619   }
2620   return rare_data->unresolved_private_names.end();
2621 }
2622 
ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail)2623 void ClassScope::ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail) {
2624   RareData* rare_data = GetRareData();
2625   if (rare_data == nullptr ||
2626       rare_data->unresolved_private_names.end() == tail) {
2627     return;
2628   }
2629 
2630   bool tail_is_empty = tail == UnresolvedList::Iterator();
2631   if (tail_is_empty) {
2632     // If the saved tail is empty, the list used to be empty, so clear it.
2633     rare_data->unresolved_private_names.Clear();
2634   } else {
2635     rare_data->unresolved_private_names.Rewind(tail);
2636   }
2637 }
2638 
MigrateUnresolvedPrivateNameTail(AstNodeFactory * ast_node_factory,UnresolvedList::Iterator tail)2639 void ClassScope::MigrateUnresolvedPrivateNameTail(
2640     AstNodeFactory* ast_node_factory, UnresolvedList::Iterator tail) {
2641   RareData* rare_data = GetRareData();
2642   if (rare_data == nullptr ||
2643       rare_data->unresolved_private_names.end() == tail) {
2644     return;
2645   }
2646   UnresolvedList migrated_names;
2647 
2648   // If the saved tail is empty, the list used to be empty, so we should
2649   // migrate everything after the head.
2650   bool tail_is_empty = tail == UnresolvedList::Iterator();
2651   UnresolvedList::Iterator it =
2652       tail_is_empty ? rare_data->unresolved_private_names.begin() : tail;
2653 
2654   for (; it != rare_data->unresolved_private_names.end(); ++it) {
2655     VariableProxy* proxy = *it;
2656     VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
2657     migrated_names.Add(copy);
2658   }
2659 
2660   // Replace with the migrated copies.
2661   if (tail_is_empty) {
2662     rare_data->unresolved_private_names.Clear();
2663   } else {
2664     rare_data->unresolved_private_names.Rewind(tail);
2665   }
2666   rare_data->unresolved_private_names.Append(std::move(migrated_names));
2667 }
2668 
LookupPrivateNameInScopeInfo(const AstRawString * name)2669 Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) {
2670   DCHECK(!scope_info_.is_null());
2671   DCHECK_NULL(LookupLocalPrivateName(name));
2672   DisallowHeapAllocation no_gc;
2673 
2674   String name_handle = *name->string();
2675   VariableMode mode;
2676   InitializationFlag init_flag;
2677   MaybeAssignedFlag maybe_assigned_flag;
2678   IsStaticFlag is_static_flag;
2679   int index =
2680       ScopeInfo::ContextSlotIndex(*scope_info_, name_handle, &mode, &init_flag,
2681                                   &maybe_assigned_flag, &is_static_flag);
2682   if (index < 0) {
2683     return nullptr;
2684   }
2685 
2686   DCHECK(IsConstVariableMode(mode));
2687   DCHECK_EQ(init_flag, InitializationFlag::kNeedsInitialization);
2688   DCHECK_EQ(maybe_assigned_flag, MaybeAssignedFlag::kNotAssigned);
2689 
2690   // Add the found private name to the map to speed up subsequent
2691   // lookups for the same name.
2692   bool was_added;
2693   Variable* var = DeclarePrivateName(name, mode, is_static_flag, &was_added);
2694   DCHECK(was_added);
2695   var->AllocateTo(VariableLocation::CONTEXT, index);
2696   return var;
2697 }
2698 
LookupPrivateName(VariableProxy * proxy)2699 Variable* ClassScope::LookupPrivateName(VariableProxy* proxy) {
2700   DCHECK(!proxy->is_resolved());
2701 
2702   for (PrivateNameScopeIterator scope_iter(this); !scope_iter.Done();
2703        scope_iter.Next()) {
2704     ClassScope* scope = scope_iter.GetScope();
2705     // Try finding it in the private name map first, if it can't be found,
2706     // try the deseralized scope info.
2707     Variable* var = scope->LookupLocalPrivateName(proxy->raw_name());
2708     if (var == nullptr && !scope->scope_info_.is_null()) {
2709       var = scope->LookupPrivateNameInScopeInfo(proxy->raw_name());
2710     }
2711     if (var != nullptr) {
2712       return var;
2713     }
2714   }
2715   return nullptr;
2716 }
2717 
ResolvePrivateNames(ParseInfo * info)2718 bool ClassScope::ResolvePrivateNames(ParseInfo* info) {
2719   RareData* rare_data = GetRareData();
2720   if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) {
2721     return true;
2722   }
2723 
2724   UnresolvedList& list = rare_data->unresolved_private_names;
2725   for (VariableProxy* proxy : list) {
2726     Variable* var = LookupPrivateName(proxy);
2727     if (var == nullptr) {
2728       // It's only possible to fail to resolve private names here if
2729       // this is at the top level or the private name is accessed through eval.
2730       DCHECK(info->flags().is_eval() || outer_scope_->is_script_scope());
2731       Scanner::Location loc = proxy->location();
2732       info->pending_error_handler()->ReportMessageAt(
2733           loc.beg_pos, loc.end_pos,
2734           MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name());
2735       return false;
2736     } else {
2737       proxy->BindTo(var);
2738     }
2739   }
2740 
2741   // By now all unresolved private names should be resolved so
2742   // clear the list.
2743   list.Clear();
2744   return true;
2745 }
2746 
ResolvePrivateNamesPartially()2747 VariableProxy* ClassScope::ResolvePrivateNamesPartially() {
2748   RareData* rare_data = GetRareData();
2749   if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) {
2750     return nullptr;
2751   }
2752 
2753   PrivateNameScopeIterator private_name_scope_iter(this);
2754   private_name_scope_iter.Next();
2755   UnresolvedList& unresolved = rare_data->unresolved_private_names;
2756   bool has_private_names = rare_data->private_name_map.capacity() > 0;
2757 
2758   // If the class itself does not have private names, nor does it have
2759   // an outer private name scope, then we are certain any private name access
2760   // inside cannot be resolved.
2761   if (!has_private_names && private_name_scope_iter.Done() &&
2762       !unresolved.is_empty()) {
2763     return unresolved.first();
2764   }
2765 
2766   for (VariableProxy* proxy = unresolved.first(); proxy != nullptr;) {
2767     DCHECK(proxy->IsPrivateName());
2768     VariableProxy* next = proxy->next_unresolved();
2769     unresolved.Remove(proxy);
2770     Variable* var = nullptr;
2771 
2772     // If we can find private name in the current class scope, we can bind
2773     // them immediately because it's going to shadow any outer private names.
2774     if (has_private_names) {
2775       var = LookupLocalPrivateName(proxy->raw_name());
2776       if (var != nullptr) {
2777         var->set_is_used();
2778         proxy->BindTo(var);
2779         // If the variable being accessed is a static private method, we need to
2780         // save the class variable in the context to check that the receiver is
2781         // the class during runtime.
2782         has_explicit_static_private_methods_access_ |=
2783             (var->is_static() &&
2784              IsPrivateMethodOrAccessorVariableMode(var->mode()));
2785       }
2786     }
2787 
2788     // If the current scope does not have declared private names,
2789     // try looking from the outer class scope later.
2790     if (var == nullptr) {
2791       // There's no outer private name scope so we are certain that the variable
2792       // cannot be resolved later.
2793       if (private_name_scope_iter.Done()) {
2794         return proxy;
2795       }
2796 
2797       // The private name may be found later in the outer private name scope, so
2798       // push it to the outer sopce.
2799       private_name_scope_iter.AddUnresolvedPrivateName(proxy);
2800     }
2801 
2802     proxy = next;
2803   }
2804 
2805   DCHECK(unresolved.is_empty());
2806   return nullptr;
2807 }
2808 
DeclareBrandVariable(AstValueFactory * ast_value_factory,IsStaticFlag is_static_flag,int class_token_pos)2809 Variable* ClassScope::DeclareBrandVariable(AstValueFactory* ast_value_factory,
2810                                            IsStaticFlag is_static_flag,
2811                                            int class_token_pos) {
2812   DCHECK_IMPLIES(GetRareData() != nullptr, GetRareData()->brand == nullptr);
2813   bool was_added;
2814   Variable* brand = Declare(zone(), ast_value_factory->dot_brand_string(),
2815                             VariableMode::kConst, NORMAL_VARIABLE,
2816                             InitializationFlag::kNeedsInitialization,
2817                             MaybeAssignedFlag::kNotAssigned, &was_added);
2818   DCHECK(was_added);
2819   brand->set_is_static_flag(is_static_flag);
2820   brand->ForceContextAllocation();
2821   brand->set_is_used();
2822   EnsureRareData()->brand = brand;
2823   brand->set_initializer_position(class_token_pos);
2824   return brand;
2825 }
2826 
DeclareClassVariable(AstValueFactory * ast_value_factory,const AstRawString * name,int class_token_pos)2827 Variable* ClassScope::DeclareClassVariable(AstValueFactory* ast_value_factory,
2828                                            const AstRawString* name,
2829                                            int class_token_pos) {
2830   DCHECK_NULL(class_variable_);
2831   bool was_added;
2832   class_variable_ =
2833       Declare(zone(), name == nullptr ? ast_value_factory->dot_string() : name,
2834               VariableMode::kConst, NORMAL_VARIABLE,
2835               InitializationFlag::kNeedsInitialization,
2836               MaybeAssignedFlag::kMaybeAssigned, &was_added);
2837   DCHECK(was_added);
2838   class_variable_->set_initializer_position(class_token_pos);
2839   return class_variable_;
2840 }
2841 
PrivateNameScopeIterator(Scope * start)2842 PrivateNameScopeIterator::PrivateNameScopeIterator(Scope* start)
2843     : start_scope_(start), current_scope_(start) {
2844   if (!start->is_class_scope() || start->AsClassScope()->IsParsingHeritage()) {
2845     Next();
2846   }
2847 }
2848 
Next()2849 void PrivateNameScopeIterator::Next() {
2850   DCHECK(!Done());
2851   Scope* inner = current_scope_;
2852   Scope* scope = inner->outer_scope();
2853   while (scope != nullptr) {
2854     if (scope->is_class_scope()) {
2855       if (!inner->private_name_lookup_skips_outer_class()) {
2856         current_scope_ = scope;
2857         return;
2858       }
2859       skipped_any_scopes_ = true;
2860     }
2861     inner = scope;
2862     scope = scope->outer_scope();
2863   }
2864   current_scope_ = nullptr;
2865 }
2866 
AddUnresolvedPrivateName(VariableProxy * proxy)2867 void PrivateNameScopeIterator::AddUnresolvedPrivateName(VariableProxy* proxy) {
2868   // During a reparse, current_scope_->already_resolved_ may be true here,
2869   // because the class scope is deserialized while the function scope inside may
2870   // be new.
2871   DCHECK(!proxy->is_resolved());
2872   DCHECK(proxy->IsPrivateName());
2873   GetScope()->EnsureRareData()->unresolved_private_names.Add(proxy);
2874   // Any closure scope that contain uses of private names that skips over a
2875   // class scope due to heritage expressions need private name context chain
2876   // recalculation, since not all scopes require a Context or ScopeInfo. See
2877   // comment in DeclarationScope::RecalcPrivateNameContextChain.
2878   if (V8_UNLIKELY(skipped_any_scopes_)) {
2879     start_scope_->GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc();
2880   }
2881 }
2882 
2883 }  // namespace internal
2884 }  // namespace v8
2885