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