• 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/accessors.h"
10 #include "src/ast/ast.h"
11 #include "src/bootstrapper.h"
12 #include "src/counters.h"
13 #include "src/messages.h"
14 #include "src/objects-inl.h"
15 #include "src/objects/module-info.h"
16 #include "src/objects/scope-info.h"
17 #include "src/parsing/parse-info.h"
18 #include "src/parsing/preparsed-scope-data.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 namespace {
24 void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1);
25 void* kDummyPreParserLexicalVariable = reinterpret_cast<void*>(0x2);
26 
IsLexical(Variable * variable)27 bool IsLexical(Variable* variable) {
28   if (variable == kDummyPreParserLexicalVariable) return true;
29   if (variable == kDummyPreParserVariable) return false;
30   return IsLexicalVariableMode(variable->mode());
31 }
32 
33 }  // namespace
34 
35 // ----------------------------------------------------------------------------
36 // Implementation of LocalsMap
37 //
38 // Note: We are storing the handle locations as key values in the hash map.
39 //       When inserting a new variable via Declare(), we rely on the fact that
40 //       the handle location remains alive for the duration of that variable
41 //       use. Because a Variable holding a handle with the same location exists
42 //       this is ensured.
43 
VariableMap(Zone * zone)44 VariableMap::VariableMap(Zone* zone)
45     : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
46 
Declare(Zone * zone,Scope * scope,const AstRawString * name,VariableMode mode,VariableKind kind,InitializationFlag initialization_flag,MaybeAssignedFlag maybe_assigned_flag,bool * added)47 Variable* VariableMap::Declare(Zone* zone, Scope* scope,
48                                const AstRawString* name, VariableMode mode,
49                                VariableKind kind,
50                                InitializationFlag initialization_flag,
51                                MaybeAssignedFlag maybe_assigned_flag,
52                                bool* added) {
53   // AstRawStrings are unambiguous, i.e., the same string is always represented
54   // by the same AstRawString*.
55   // FIXME(marja): fix the type of Lookup.
56   Entry* p =
57       ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
58                                   ZoneAllocationPolicy(zone));
59   if (added) *added = p->value == nullptr;
60   if (p->value == nullptr) {
61     // The variable has not been declared yet -> insert it.
62     DCHECK_EQ(name, p->key);
63     p->value = new (zone) Variable(scope, name, mode, kind, initialization_flag,
64                                    maybe_assigned_flag);
65   }
66   return reinterpret_cast<Variable*>(p->value);
67 }
68 
DeclareName(Zone * zone,const AstRawString * name,VariableMode mode)69 Variable* VariableMap::DeclareName(Zone* zone, const AstRawString* name,
70                                    VariableMode mode) {
71   Entry* p =
72       ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
73                                   ZoneAllocationPolicy(zone));
74   if (p->value == nullptr) {
75     // The variable has not been declared yet -> insert it.
76     DCHECK_EQ(name, p->key);
77     p->value =
78         mode == VAR ? kDummyPreParserVariable : kDummyPreParserLexicalVariable;
79   }
80   return reinterpret_cast<Variable*>(p->value);
81 }
82 
Remove(Variable * var)83 void VariableMap::Remove(Variable* var) {
84   const AstRawString* name = var->raw_name();
85   ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash());
86 }
87 
Add(Zone * zone,Variable * var)88 void VariableMap::Add(Zone* zone, Variable* var) {
89   const AstRawString* name = var->raw_name();
90   Entry* p =
91       ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
92                                   ZoneAllocationPolicy(zone));
93   DCHECK_NULL(p->value);
94   DCHECK_EQ(name, p->key);
95   p->value = var;
96 }
97 
Lookup(const AstRawString * name)98 Variable* VariableMap::Lookup(const AstRawString* name) {
99   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash());
100   if (p != NULL) {
101     DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
102     DCHECK(p->value != NULL);
103     return reinterpret_cast<Variable*>(p->value);
104   }
105   return NULL;
106 }
107 
set_statement(Statement * statement)108 void SloppyBlockFunctionMap::Delegate::set_statement(Statement* statement) {
109   if (statement_ != nullptr) {
110     statement_->set_statement(statement);
111   }
112 }
113 
SloppyBlockFunctionMap(Zone * zone)114 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone)
115     : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
116 
Declare(Zone * zone,const AstRawString * name,SloppyBlockFunctionMap::Delegate * delegate)117 void SloppyBlockFunctionMap::Declare(
118     Zone* zone, const AstRawString* name,
119     SloppyBlockFunctionMap::Delegate* delegate) {
120   // AstRawStrings are unambiguous, i.e., the same string is always represented
121   // by the same AstRawString*.
122   Entry* p =
123       ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
124                                   ZoneAllocationPolicy(zone));
125   delegate->set_next(static_cast<SloppyBlockFunctionMap::Delegate*>(p->value));
126   p->value = delegate;
127 }
128 
129 // ----------------------------------------------------------------------------
130 // Implementation of Scope
131 
Scope(Zone * zone)132 Scope::Scope(Zone* zone)
133     : zone_(zone),
134       outer_scope_(nullptr),
135       variables_(zone),
136       scope_type_(SCRIPT_SCOPE) {
137   SetDefaults();
138 }
139 
Scope(Zone * zone,Scope * outer_scope,ScopeType scope_type)140 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
141     : zone_(zone),
142       outer_scope_(outer_scope),
143       variables_(zone),
144       scope_type_(scope_type) {
145   DCHECK_NE(SCRIPT_SCOPE, scope_type);
146   SetDefaults();
147   set_language_mode(outer_scope->language_mode());
148   force_context_allocation_ =
149       !is_function_scope() && outer_scope->has_forced_context_allocation();
150   outer_scope_->AddInnerScope(this);
151 }
152 
Snapshot(Scope * scope)153 Scope::Snapshot::Snapshot(Scope* scope)
154     : outer_scope_(scope),
155       top_inner_scope_(scope->inner_scope_),
156       top_unresolved_(scope->unresolved_),
157       top_local_(scope->GetClosureScope()->locals_.end()),
158       top_decl_(scope->GetClosureScope()->decls_.end()) {}
159 
DeclarationScope(Zone * zone,AstValueFactory * ast_value_factory)160 DeclarationScope::DeclarationScope(Zone* zone,
161                                    AstValueFactory* ast_value_factory)
162     : Scope(zone),
163       function_kind_(kNormalFunction),
164       params_(4, zone),
165       sloppy_block_function_map_(zone) {
166   DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
167   SetDefaults();
168 
169   // Make sure that if we don't find the global 'this', it won't be declared as
170   // a regular dynamic global by predeclaring it with the right variable kind.
171   DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE);
172 }
173 
DeclarationScope(Zone * zone,Scope * outer_scope,ScopeType scope_type,FunctionKind function_kind)174 DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
175                                    ScopeType scope_type,
176                                    FunctionKind function_kind)
177     : Scope(zone, outer_scope, scope_type),
178       function_kind_(function_kind),
179       params_(4, zone),
180       sloppy_block_function_map_(zone) {
181   DCHECK_NE(scope_type, SCRIPT_SCOPE);
182   SetDefaults();
183   asm_function_ = outer_scope_->IsAsmModule();
184 }
185 
ModuleScope(DeclarationScope * script_scope,AstValueFactory * ast_value_factory)186 ModuleScope::ModuleScope(DeclarationScope* script_scope,
187                          AstValueFactory* ast_value_factory)
188     : DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
189                        kModule) {
190   Zone* zone = ast_value_factory->zone();
191   module_descriptor_ = new (zone) ModuleDescriptor(zone);
192   set_language_mode(STRICT);
193   DeclareThis(ast_value_factory);
194 }
195 
ModuleScope(Isolate * isolate,Handle<ScopeInfo> scope_info,AstValueFactory * avfactory)196 ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
197                          AstValueFactory* avfactory)
198     : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info) {
199   Zone* zone = avfactory->zone();
200   Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(), isolate);
201 
202   set_language_mode(STRICT);
203   module_descriptor_ = new (zone) ModuleDescriptor(zone);
204 
205   // Deserialize special exports.
206   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
207   for (int i = 0, n = special_exports->length(); i < n; ++i) {
208     Handle<ModuleInfoEntry> serialized_entry(
209         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
210     module_descriptor_->AddSpecialExport(
211         ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
212                                              serialized_entry),
213         avfactory->zone());
214   }
215 
216   // Deserialize regular exports.
217   module_descriptor_->DeserializeRegularExports(isolate, avfactory,
218                                                 module_info);
219 
220   // Deserialize namespace imports.
221   Handle<FixedArray> namespace_imports(module_info->namespace_imports(),
222                                        isolate);
223   for (int i = 0, n = namespace_imports->length(); i < n; ++i) {
224     Handle<ModuleInfoEntry> serialized_entry(
225         ModuleInfoEntry::cast(namespace_imports->get(i)), isolate);
226     module_descriptor_->AddNamespaceImport(
227         ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
228                                              serialized_entry),
229         avfactory->zone());
230   }
231 
232   // Deserialize regular imports.
233   Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
234   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
235     Handle<ModuleInfoEntry> serialized_entry(
236         ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
237     module_descriptor_->AddRegularImport(ModuleDescriptor::Entry::Deserialize(
238         isolate, avfactory, serialized_entry));
239   }
240 }
241 
Scope(Zone * zone,ScopeType scope_type,Handle<ScopeInfo> scope_info)242 Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
243     : zone_(zone),
244       outer_scope_(nullptr),
245       variables_(zone),
246       scope_info_(scope_info),
247       scope_type_(scope_type) {
248   DCHECK(!scope_info.is_null());
249   SetDefaults();
250 #ifdef DEBUG
251   already_resolved_ = true;
252 #endif
253   if (scope_info->CallsEval()) RecordEvalCall();
254   set_language_mode(scope_info->language_mode());
255   num_heap_slots_ = scope_info->ContextLength();
256   DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
257 }
258 
DeclarationScope(Zone * zone,ScopeType scope_type,Handle<ScopeInfo> scope_info)259 DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
260                                    Handle<ScopeInfo> scope_info)
261     : Scope(zone, scope_type, scope_info),
262       function_kind_(scope_info->function_kind()),
263       params_(0, zone),
264       sloppy_block_function_map_(zone) {
265   DCHECK_NE(scope_type, SCRIPT_SCOPE);
266   SetDefaults();
267 }
268 
Scope(Zone * zone,const AstRawString * catch_variable_name,Handle<ScopeInfo> scope_info)269 Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
270              Handle<ScopeInfo> scope_info)
271     : zone_(zone),
272       outer_scope_(nullptr),
273       variables_(zone),
274       scope_info_(scope_info),
275       scope_type_(CATCH_SCOPE) {
276   SetDefaults();
277 #ifdef DEBUG
278   already_resolved_ = true;
279 #endif
280   // Cache the catch variable, even though it's also available via the
281   // scope_info, as the parser expects that a catch scope always has the catch
282   // variable as first and only variable.
283   Variable* variable = Declare(zone, catch_variable_name, VAR);
284   AllocateHeapSlot(variable);
285 }
286 
SetDefaults()287 void DeclarationScope::SetDefaults() {
288   is_declaration_scope_ = true;
289   has_simple_parameters_ = true;
290   asm_module_ = false;
291   asm_function_ = false;
292   force_eager_compilation_ = false;
293   has_arguments_parameter_ = false;
294   scope_uses_super_property_ = false;
295   has_rest_ = false;
296   receiver_ = nullptr;
297   new_target_ = nullptr;
298   function_ = nullptr;
299   arguments_ = nullptr;
300   rare_data_ = nullptr;
301   should_eager_compile_ = false;
302   was_lazily_parsed_ = false;
303 #ifdef DEBUG
304   DeclarationScope* outer_declaration_scope =
305       outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
306   is_being_lazily_parsed_ =
307       outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
308                               : false;
309 #endif
310 }
311 
SetDefaults()312 void Scope::SetDefaults() {
313 #ifdef DEBUG
314   scope_name_ = nullptr;
315   already_resolved_ = false;
316   needs_migration_ = false;
317 #endif
318   inner_scope_ = nullptr;
319   sibling_ = nullptr;
320   unresolved_ = nullptr;
321 
322   start_position_ = kNoSourcePosition;
323   end_position_ = kNoSourcePosition;
324 
325   num_stack_slots_ = 0;
326   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
327 
328   set_language_mode(SLOPPY);
329 
330   scope_calls_eval_ = false;
331   scope_nonlinear_ = false;
332   is_hidden_ = false;
333   is_debug_evaluate_scope_ = false;
334 
335   inner_scope_calls_eval_ = false;
336   force_context_allocation_ = false;
337 
338   is_declaration_scope_ = false;
339 }
340 
HasSimpleParameters()341 bool Scope::HasSimpleParameters() {
342   DeclarationScope* scope = GetClosureScope();
343   return !scope->is_function_scope() || scope->has_simple_parameters();
344 }
345 
ShouldEagerCompile() const346 bool DeclarationScope::ShouldEagerCompile() const {
347   return force_eager_compilation_ || should_eager_compile_;
348 }
349 
set_should_eager_compile()350 void DeclarationScope::set_should_eager_compile() {
351   should_eager_compile_ = !was_lazily_parsed_;
352 }
353 
set_asm_module()354 void DeclarationScope::set_asm_module() {
355   asm_module_ = true;
356   // Mark any existing inner function scopes as asm function scopes.
357   for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) {
358     if (inner->is_function_scope()) {
359       inner->AsDeclarationScope()->set_asm_function();
360     }
361   }
362 }
363 
IsAsmModule() const364 bool Scope::IsAsmModule() const {
365   return is_function_scope() && AsDeclarationScope()->asm_module();
366 }
367 
IsAsmFunction() const368 bool Scope::IsAsmFunction() const {
369   return is_function_scope() && AsDeclarationScope()->asm_function();
370 }
371 
DeserializeScopeChain(Isolate * isolate,Zone * zone,ScopeInfo * scope_info,DeclarationScope * script_scope,AstValueFactory * ast_value_factory,DeserializationMode deserialization_mode)372 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
373                                     ScopeInfo* scope_info,
374                                     DeclarationScope* script_scope,
375                                     AstValueFactory* ast_value_factory,
376                                     DeserializationMode deserialization_mode) {
377   // Reconstruct the outer scope chain from a closure's context chain.
378   Scope* current_scope = nullptr;
379   Scope* innermost_scope = nullptr;
380   Scope* outer_scope = nullptr;
381   while (scope_info) {
382     if (scope_info->scope_type() == WITH_SCOPE) {
383       // For scope analysis, debug-evaluate is equivalent to a with scope.
384       outer_scope = new (zone) Scope(zone, WITH_SCOPE, handle(scope_info));
385 
386       // TODO(yangguo): Remove once debug-evaluate properly keeps track of the
387       // function scope in which we are evaluating.
388       if (scope_info->IsDebugEvaluateScope()) {
389         outer_scope->set_is_debug_evaluate_scope();
390       }
391     } else if (scope_info->scope_type() == SCRIPT_SCOPE) {
392       // If we reach a script scope, it's the outermost scope. Install the
393       // scope info of this script context onto the existing script scope to
394       // avoid nesting script scopes.
395       if (deserialization_mode == DeserializationMode::kIncludingVariables) {
396         script_scope->SetScriptScopeInfo(handle(scope_info));
397       }
398       DCHECK(!scope_info->HasOuterScopeInfo());
399       break;
400     } else if (scope_info->scope_type() == FUNCTION_SCOPE) {
401       outer_scope =
402           new (zone) DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info));
403       if (scope_info->IsAsmFunction())
404         outer_scope->AsDeclarationScope()->set_asm_function();
405       if (scope_info->IsAsmModule())
406         outer_scope->AsDeclarationScope()->set_asm_module();
407     } else if (scope_info->scope_type() == EVAL_SCOPE) {
408       outer_scope =
409           new (zone) DeclarationScope(zone, EVAL_SCOPE, handle(scope_info));
410     } else if (scope_info->scope_type() == BLOCK_SCOPE) {
411       if (scope_info->is_declaration_scope()) {
412         outer_scope =
413             new (zone) DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info));
414       } else {
415         outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info));
416       }
417     } else if (scope_info->scope_type() == MODULE_SCOPE) {
418       outer_scope = new (zone)
419           ModuleScope(isolate, handle(scope_info), ast_value_factory);
420     } else {
421       DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
422       DCHECK_EQ(scope_info->LocalCount(), 1);
423       String* name = scope_info->LocalName(0);
424       outer_scope = new (zone)
425           Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
426                 handle(scope_info));
427     }
428     if (deserialization_mode == DeserializationMode::kScopesOnly) {
429       outer_scope->scope_info_ = Handle<ScopeInfo>::null();
430     }
431     if (current_scope != nullptr) {
432       outer_scope->AddInnerScope(current_scope);
433     }
434     current_scope = outer_scope;
435     if (innermost_scope == nullptr) innermost_scope = current_scope;
436     scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
437                                                  : nullptr;
438   }
439 
440   if (innermost_scope == nullptr) return script_scope;
441   script_scope->AddInnerScope(current_scope);
442   return innermost_scope;
443 }
444 
AsDeclarationScope()445 DeclarationScope* Scope::AsDeclarationScope() {
446   DCHECK(is_declaration_scope());
447   return static_cast<DeclarationScope*>(this);
448 }
449 
AsDeclarationScope() const450 const DeclarationScope* Scope::AsDeclarationScope() const {
451   DCHECK(is_declaration_scope());
452   return static_cast<const DeclarationScope*>(this);
453 }
454 
AsModuleScope()455 ModuleScope* Scope::AsModuleScope() {
456   DCHECK(is_module_scope());
457   return static_cast<ModuleScope*>(this);
458 }
459 
AsModuleScope() const460 const ModuleScope* Scope::AsModuleScope() const {
461   DCHECK(is_module_scope());
462   return static_cast<const ModuleScope*>(this);
463 }
464 
num_parameters() const465 int Scope::num_parameters() const {
466   return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0;
467 }
468 
DeclareSloppyBlockFunction(const AstRawString * name,Scope * scope,SloppyBlockFunctionStatement * statement)469 void DeclarationScope::DeclareSloppyBlockFunction(
470     const AstRawString* name, Scope* scope,
471     SloppyBlockFunctionStatement* statement) {
472   auto* delegate =
473       new (zone()) SloppyBlockFunctionMap::Delegate(scope, statement);
474   sloppy_block_function_map_.Declare(zone(), name, delegate);
475 }
476 
HoistSloppyBlockFunctions(AstNodeFactory * factory)477 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
478   DCHECK(is_sloppy(language_mode()));
479   DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
480          (is_block_scope() && outer_scope()->is_function_scope()));
481   DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
482   DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
483 
484   bool has_simple_parameters = HasSimpleParameters();
485   // For each variable which is used as a function declaration in a sloppy
486   // block,
487   SloppyBlockFunctionMap* map = sloppy_block_function_map();
488   for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
489     AstRawString* name = static_cast<AstRawString*>(p->key);
490 
491     // If the variable wouldn't conflict with a lexical declaration
492     // or parameter,
493 
494     // Check if there's a conflict with a parameter.
495     // This depends on the fact that functions always have a scope solely to
496     // hold complex parameters, and the names local to that scope are
497     // precisely the names of the parameters. IsDeclaredParameter(name) does
498     // not hold for names declared by complex parameters, nor are those
499     // bindings necessarily declared lexically, so we have to check for them
500     // explicitly. On the other hand, if there are not complex parameters,
501     // it is sufficient to just check IsDeclaredParameter.
502     if (!has_simple_parameters) {
503       if (outer_scope_->LookupLocal(name) != nullptr) {
504         continue;
505       }
506     } else {
507       if (IsDeclaredParameter(name)) {
508         continue;
509       }
510     }
511 
512     Variable* created_variable = nullptr;
513 
514     // Write in assignments to var for each block-scoped function declaration
515     auto delegates = static_cast<SloppyBlockFunctionMap::Delegate*>(p->value);
516 
517     DeclarationScope* decl_scope = this;
518     while (decl_scope->is_eval_scope()) {
519       decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
520     }
521     Scope* outer_scope = decl_scope->outer_scope();
522 
523     for (SloppyBlockFunctionMap::Delegate* delegate = delegates;
524          delegate != nullptr; delegate = delegate->next()) {
525       // Check if there's a conflict with a lexical declaration
526       Scope* query_scope = delegate->scope()->outer_scope();
527       Variable* var = nullptr;
528       bool should_hoist = true;
529 
530       // Note that we perform this loop for each delegate named 'name',
531       // which may duplicate work if those delegates share scopes.
532       // It is not sufficient to just do a Lookup on query_scope: for
533       // example, that does not prevent hoisting of the function in
534       // `{ let e; try {} catch (e) { function e(){} } }`
535       do {
536         var = query_scope->LookupLocal(name);
537         if (var != nullptr && IsLexical(var)) {
538           should_hoist = false;
539           break;
540         }
541         query_scope = query_scope->outer_scope();
542       } while (query_scope != outer_scope);
543 
544       if (!should_hoist) continue;
545 
546       // Declare a var-style binding for the function in the outer scope
547       if (factory) {
548         DCHECK(!is_being_lazily_parsed_);
549         if (created_variable == nullptr) {
550           VariableProxy* proxy =
551               factory->NewVariableProxy(name, NORMAL_VARIABLE);
552           auto declaration =
553               factory->NewVariableDeclaration(proxy, this, kNoSourcePosition);
554           // Based on the preceding check, it doesn't matter what we pass as
555           // allow_harmony_restrictive_generators and
556           // sloppy_mode_block_scope_function_redefinition.
557           bool ok = true;
558           created_variable = DeclareVariable(
559               declaration, VAR, Variable::DefaultInitializationFlag(VAR), false,
560               nullptr, &ok);
561           CHECK(ok);  // Based on the preceding check, this should not fail
562         }
563 
564         Expression* assignment = factory->NewAssignment(
565             Token::ASSIGN, NewUnresolved(factory, name),
566             delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition);
567         Statement* statement =
568             factory->NewExpressionStatement(assignment, kNoSourcePosition);
569         delegate->set_statement(statement);
570       } else {
571         DCHECK(is_being_lazily_parsed_);
572         if (created_variable == nullptr) {
573           created_variable = DeclareVariableName(name, VAR);
574           if (created_variable != kDummyPreParserVariable &&
575               created_variable != kDummyPreParserLexicalVariable) {
576             DCHECK(FLAG_preparser_scope_analysis);
577             created_variable->set_maybe_assigned();
578           }
579         }
580       }
581     }
582   }
583 }
584 
Analyze(ParseInfo * info,AnalyzeMode mode)585 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) {
586   RuntimeCallTimerScope runtimeTimer(info->isolate(),
587                                      &RuntimeCallStats::CompileScopeAnalysis);
588   DCHECK(info->literal() != NULL);
589   DeclarationScope* scope = info->literal()->scope();
590 
591   Handle<ScopeInfo> outer_scope_info;
592   if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) {
593     if (scope->outer_scope()) {
594       DeclarationScope* script_scope = new (info->zone())
595           DeclarationScope(info->zone(), info->ast_value_factory());
596       info->set_script_scope(script_scope);
597       scope->ReplaceOuterScope(Scope::DeserializeScopeChain(
598           info->isolate(), info->zone(), *outer_scope_info, script_scope,
599           info->ast_value_factory(),
600           Scope::DeserializationMode::kIncludingVariables));
601     } else {
602       DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE);
603       scope->SetScriptScopeInfo(outer_scope_info);
604     }
605   }
606 
607   if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
608     AstNodeFactory factory(info->ast_value_factory());
609     scope->HoistSloppyBlockFunctions(&factory);
610   }
611 
612   // We are compiling one of four cases:
613   // 1) top-level code,
614   // 2) a function/eval/module on the top-level
615   // 3) a function/eval in a scope that was already resolved.
616   // 4) an asm.js function
617   DCHECK(scope->scope_type() == SCRIPT_SCOPE ||
618          scope->outer_scope()->scope_type() == SCRIPT_SCOPE ||
619          scope->outer_scope()->already_resolved_ ||
620          (info->asm_function_scope() && scope->is_function_scope()));
621 
622   // The outer scope is never lazy.
623   scope->set_should_eager_compile();
624 
625   scope->AllocateVariables(info, mode);
626 
627   // Ensuring that the outer script scope has a scope info avoids having
628   // special case for native contexts vs other contexts.
629   if (info->script_scope()->scope_info_.is_null()) {
630     info->script_scope()->scope_info_ =
631         handle(ScopeInfo::Empty(info->isolate()));
632   }
633 
634 #ifdef DEBUG
635   if (info->script_is_native() ? FLAG_print_builtin_scopes
636                                : FLAG_print_scopes) {
637     PrintF("Global scope:\n");
638     scope->Print();
639   }
640   scope->CheckScopePositions();
641   scope->CheckZones();
642 #endif
643 }
644 
DeclareThis(AstValueFactory * ast_value_factory)645 void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
646   DCHECK(!already_resolved_);
647   DCHECK(is_declaration_scope());
648   DCHECK(has_this_declaration());
649 
650   bool derived_constructor = IsDerivedConstructor(function_kind_);
651   Variable* var =
652       Declare(zone(), ast_value_factory->this_string(),
653               derived_constructor ? CONST : VAR, THIS_VARIABLE,
654               derived_constructor ? kNeedsInitialization : kCreatedInitialized);
655   receiver_ = var;
656 }
657 
DeclareArguments(AstValueFactory * ast_value_factory)658 void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
659   DCHECK(is_function_scope());
660   DCHECK(!is_arrow_scope());
661 
662   arguments_ = LookupLocal(ast_value_factory->arguments_string());
663   if (arguments_ == nullptr) {
664     // Declare 'arguments' variable which exists in all non arrow functions.
665     // Note that it might never be accessed, in which case it won't be
666     // allocated during variable allocation.
667     arguments_ = Declare(zone(), ast_value_factory->arguments_string(), VAR);
668   } else if (IsLexical(arguments_)) {
669     // Check if there's lexically declared variable named arguments to avoid
670     // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
671     arguments_ = nullptr;
672   }
673 }
674 
DeclareDefaultFunctionVariables(AstValueFactory * ast_value_factory)675 void DeclarationScope::DeclareDefaultFunctionVariables(
676     AstValueFactory* ast_value_factory) {
677   DCHECK(is_function_scope());
678   DCHECK(!is_arrow_scope());
679 
680   DeclareThis(ast_value_factory);
681   new_target_ = Declare(zone(), ast_value_factory->new_target_string(), CONST);
682 
683   if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
684       IsAccessorFunction(function_kind_)) {
685     EnsureRareData()->this_function =
686         Declare(zone(), ast_value_factory->this_function_string(), CONST);
687   }
688 }
689 
DeclareFunctionVar(const AstRawString * name)690 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) {
691   DCHECK(is_function_scope());
692   DCHECK_NULL(function_);
693   DCHECK_NULL(variables_.Lookup(name));
694   VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
695                                                  : NORMAL_VARIABLE;
696   function_ =
697       new (zone()) Variable(this, name, CONST, kind, kCreatedInitialized);
698   if (calls_sloppy_eval()) {
699     NonLocal(name, DYNAMIC);
700   } else {
701     variables_.Add(zone(), function_);
702   }
703   return function_;
704 }
705 
DeclareGeneratorObjectVar(const AstRawString * name)706 Variable* DeclarationScope::DeclareGeneratorObjectVar(
707     const AstRawString* name) {
708   DCHECK(is_function_scope() || is_module_scope());
709   DCHECK_NULL(generator_object_var());
710 
711   Variable* result = EnsureRareData()->generator_object =
712       NewTemporary(name, kNotAssigned);
713   result->set_is_used();
714   return result;
715 }
716 
DeclarePromiseVar(const AstRawString * name)717 Variable* DeclarationScope::DeclarePromiseVar(const AstRawString* name) {
718   DCHECK(is_function_scope());
719   DCHECK_NULL(promise_var());
720   Variable* result = EnsureRareData()->promise = NewTemporary(name);
721   result->set_is_used();
722   return result;
723 }
724 
HasBeenRemoved() const725 bool Scope::HasBeenRemoved() const {
726   if (sibling() == this) {
727     DCHECK_NULL(inner_scope_);
728     DCHECK(is_block_scope());
729     return true;
730   }
731   return false;
732 }
733 
GetUnremovedScope()734 Scope* Scope::GetUnremovedScope() {
735   Scope* scope = this;
736   while (scope != nullptr && scope->HasBeenRemoved()) {
737     scope = scope->outer_scope();
738   }
739   DCHECK_NOT_NULL(scope);
740   return scope;
741 }
742 
FinalizeBlockScope()743 Scope* Scope::FinalizeBlockScope() {
744   DCHECK(is_block_scope());
745   DCHECK(!HasBeenRemoved());
746 
747   if (variables_.occupancy() > 0 ||
748       (is_declaration_scope() && calls_sloppy_eval())) {
749     return this;
750   }
751 
752   // Remove this scope from outer scope.
753   outer_scope()->RemoveInnerScope(this);
754 
755   // Reparent inner scopes.
756   if (inner_scope_ != nullptr) {
757     Scope* scope = inner_scope_;
758     scope->outer_scope_ = outer_scope();
759     while (scope->sibling_ != nullptr) {
760       scope = scope->sibling_;
761       scope->outer_scope_ = outer_scope();
762     }
763     scope->sibling_ = outer_scope()->inner_scope_;
764     outer_scope()->inner_scope_ = inner_scope_;
765     inner_scope_ = nullptr;
766   }
767 
768   // Move unresolved variables
769   if (unresolved_ != nullptr) {
770     if (outer_scope()->unresolved_ != nullptr) {
771       VariableProxy* unresolved = unresolved_;
772       while (unresolved->next_unresolved() != nullptr) {
773         unresolved = unresolved->next_unresolved();
774       }
775       unresolved->set_next_unresolved(outer_scope()->unresolved_);
776     }
777     outer_scope()->unresolved_ = unresolved_;
778     unresolved_ = nullptr;
779   }
780 
781   PropagateUsageFlagsToScope(outer_scope_);
782   // This block does not need a context.
783   num_heap_slots_ = 0;
784 
785   // Mark scope as removed by making it its own sibling.
786   sibling_ = this;
787   DCHECK(HasBeenRemoved());
788 
789   return nullptr;
790 }
791 
AddLocal(Variable * var)792 void DeclarationScope::AddLocal(Variable* var) {
793   DCHECK(!already_resolved_);
794   // Temporaries are only placed in ClosureScopes.
795   DCHECK_EQ(GetClosureScope(), this);
796   locals_.Add(var);
797 }
798 
Declare(Zone * zone,const AstRawString * name,VariableMode mode,VariableKind kind,InitializationFlag initialization_flag,MaybeAssignedFlag maybe_assigned_flag)799 Variable* Scope::Declare(Zone* zone, const AstRawString* name,
800                          VariableMode mode, VariableKind kind,
801                          InitializationFlag initialization_flag,
802                          MaybeAssignedFlag maybe_assigned_flag) {
803   bool added;
804   Variable* var =
805       variables_.Declare(zone, this, name, mode, kind, initialization_flag,
806                          maybe_assigned_flag, &added);
807   if (added) locals_.Add(var);
808   return var;
809 }
810 
Reparent(DeclarationScope * new_parent) const811 void Scope::Snapshot::Reparent(DeclarationScope* new_parent) const {
812   DCHECK_EQ(new_parent, outer_scope_->inner_scope_);
813   DCHECK_EQ(new_parent->outer_scope_, outer_scope_);
814   DCHECK_EQ(new_parent, new_parent->GetClosureScope());
815   DCHECK_NULL(new_parent->inner_scope_);
816   DCHECK_NULL(new_parent->unresolved_);
817   DCHECK(new_parent->locals_.is_empty());
818   Scope* inner_scope = new_parent->sibling_;
819   if (inner_scope != top_inner_scope_) {
820     for (; inner_scope->sibling() != top_inner_scope_;
821          inner_scope = inner_scope->sibling()) {
822       inner_scope->outer_scope_ = new_parent;
823       DCHECK_NE(inner_scope, new_parent);
824     }
825     inner_scope->outer_scope_ = new_parent;
826 
827     new_parent->inner_scope_ = new_parent->sibling_;
828     inner_scope->sibling_ = nullptr;
829     // Reset the sibling rather than the inner_scope_ since we
830     // want to keep new_parent there.
831     new_parent->sibling_ = top_inner_scope_;
832   }
833 
834   if (outer_scope_->unresolved_ != top_unresolved_) {
835     VariableProxy* last = outer_scope_->unresolved_;
836     while (last->next_unresolved() != top_unresolved_) {
837       last = last->next_unresolved();
838     }
839     last->set_next_unresolved(nullptr);
840     new_parent->unresolved_ = outer_scope_->unresolved_;
841     outer_scope_->unresolved_ = top_unresolved_;
842   }
843 
844   // TODO(verwaest): This currently only moves do-expression declared variables
845   // in default arguments that weren't already previously declared with the same
846   // name in the closure-scope. See
847   // test/mjsunit/harmony/default-parameter-do-expression.js.
848   DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
849 
850   new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
851   for (Variable* local : new_parent->locals_) {
852     DCHECK(local->mode() == TEMPORARY || local->mode() == VAR);
853     DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
854     DCHECK_NE(local->scope(), new_parent);
855     local->set_scope(new_parent);
856     if (local->mode() == VAR) {
857       outer_closure->variables_.Remove(local);
858       new_parent->variables_.Add(new_parent->zone(), local);
859     }
860   }
861   outer_closure->locals_.Rewind(top_local_);
862   outer_closure->decls_.Rewind(top_decl_);
863 }
864 
ReplaceOuterScope(Scope * outer)865 void Scope::ReplaceOuterScope(Scope* outer) {
866   DCHECK_NOT_NULL(outer);
867   DCHECK_NOT_NULL(outer_scope_);
868   DCHECK(!already_resolved_);
869   outer_scope_->RemoveInnerScope(this);
870   outer->AddInnerScope(this);
871   outer_scope_ = outer;
872 }
873 
874 
PropagateUsageFlagsToScope(Scope * other)875 void Scope::PropagateUsageFlagsToScope(Scope* other) {
876   DCHECK_NOT_NULL(other);
877   DCHECK(!already_resolved_);
878   DCHECK(!other->already_resolved_);
879   if (calls_eval()) other->RecordEvalCall();
880   if (inner_scope_calls_eval_) other->inner_scope_calls_eval_ = true;
881 }
882 
LookupInScopeInfo(const AstRawString * name)883 Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
884   Handle<String> name_handle = name->string();
885   // The Scope is backed up by ScopeInfo. This means it cannot operate in a
886   // heap-independent mode, and all strings must be internalized immediately. So
887   // it's ok to get the Handle<String> here.
888   // If we have a serialized scope info, we might find the variable there.
889   // There should be no local slot with the given name.
890   DCHECK_LT(scope_info_->StackSlotIndex(*name_handle), 0);
891 
892   bool found = false;
893 
894   VariableLocation location;
895   int index;
896   VariableMode mode;
897   InitializationFlag init_flag;
898   MaybeAssignedFlag maybe_assigned_flag;
899 
900   {
901     location = VariableLocation::CONTEXT;
902     index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode,
903                                         &init_flag, &maybe_assigned_flag);
904     found = index >= 0;
905   }
906 
907   if (!found && scope_type() == MODULE_SCOPE) {
908     location = VariableLocation::MODULE;
909     index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
910                                      &maybe_assigned_flag);
911     found = index != 0;
912   }
913 
914   if (!found) {
915     index = scope_info_->FunctionContextSlotIndex(*name_handle);
916     if (index < 0) return nullptr;  // Nowhere found.
917     Variable* var = AsDeclarationScope()->DeclareFunctionVar(name);
918     DCHECK_EQ(CONST, var->mode());
919     var->AllocateTo(VariableLocation::CONTEXT, index);
920     return variables_.Lookup(name);
921   }
922 
923   VariableKind kind = NORMAL_VARIABLE;
924   if (location == VariableLocation::CONTEXT &&
925       index == scope_info_->ReceiverContextSlotIndex()) {
926     kind = THIS_VARIABLE;
927   }
928   // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
929   // ARGUMENTS bindings as their corresponding VariableKind.
930 
931   Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag,
932                                      maybe_assigned_flag);
933   var->AllocateTo(location, index);
934   return var;
935 }
936 
Lookup(const AstRawString * name)937 Variable* Scope::Lookup(const AstRawString* name) {
938   for (Scope* scope = this;
939        scope != NULL;
940        scope = scope->outer_scope()) {
941     Variable* var = scope->LookupLocal(name);
942     if (var != NULL) return var;
943   }
944   return NULL;
945 }
946 
DeclareParameter(const AstRawString * name,VariableMode mode,bool is_optional,bool is_rest,bool * is_duplicate,AstValueFactory * ast_value_factory)947 Variable* DeclarationScope::DeclareParameter(
948     const AstRawString* name, VariableMode mode, bool is_optional, bool is_rest,
949     bool* is_duplicate, AstValueFactory* ast_value_factory) {
950   DCHECK(!already_resolved_);
951   DCHECK(is_function_scope() || is_module_scope());
952   DCHECK(!has_rest_);
953   DCHECK(!is_optional || !is_rest);
954   DCHECK(!is_being_lazily_parsed_);
955   DCHECK(!was_lazily_parsed_);
956   Variable* var;
957   if (mode == TEMPORARY) {
958     var = NewTemporary(name);
959   } else {
960     DCHECK_EQ(mode, VAR);
961     var = Declare(zone(), name, mode);
962     // TODO(wingo): Avoid O(n^2) check.
963     *is_duplicate = IsDeclaredParameter(name);
964   }
965   has_rest_ = is_rest;
966   params_.Add(var, zone());
967   if (name == ast_value_factory->arguments_string()) {
968     has_arguments_parameter_ = true;
969   }
970   return var;
971 }
972 
DeclareParameterName(const AstRawString * name,bool is_rest,AstValueFactory * ast_value_factory)973 Variable* DeclarationScope::DeclareParameterName(
974     const AstRawString* name, bool is_rest,
975     AstValueFactory* ast_value_factory) {
976   DCHECK(!already_resolved_);
977   DCHECK(is_function_scope() || is_module_scope());
978   DCHECK(!has_rest_ || is_rest);
979   DCHECK(is_being_lazily_parsed_);
980   has_rest_ = is_rest;
981   if (name == ast_value_factory->arguments_string()) {
982     has_arguments_parameter_ = true;
983   }
984   if (FLAG_preparser_scope_analysis) {
985     Variable* var = Declare(zone(), name, VAR);
986     params_.Add(var, zone());
987     return var;
988   }
989   DeclareVariableName(name, VAR);
990   return nullptr;
991 }
992 
DeclareLocal(const AstRawString * name,VariableMode mode,InitializationFlag init_flag,VariableKind kind,MaybeAssignedFlag maybe_assigned_flag)993 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
994                               InitializationFlag init_flag, VariableKind kind,
995                               MaybeAssignedFlag maybe_assigned_flag) {
996   DCHECK(!already_resolved_);
997   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are
998   // introduced during variable allocation, and TEMPORARY variables are
999   // allocated via NewTemporary().
1000   DCHECK(IsDeclaredVariableMode(mode));
1001   DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
1002                  mode == VAR || mode == LET || mode == CONST);
1003   DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1004   return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag);
1005 }
1006 
DeclareVariable(Declaration * declaration,VariableMode mode,InitializationFlag init,bool allow_harmony_restrictive_generators,bool * sloppy_mode_block_scope_function_redefinition,bool * ok)1007 Variable* Scope::DeclareVariable(
1008     Declaration* declaration, VariableMode mode, InitializationFlag init,
1009     bool allow_harmony_restrictive_generators,
1010     bool* sloppy_mode_block_scope_function_redefinition, bool* ok) {
1011   DCHECK(IsDeclaredVariableMode(mode));
1012   DCHECK(!already_resolved_);
1013   DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
1014   DCHECK(!GetDeclarationScope()->was_lazily_parsed());
1015 
1016   if (mode == VAR && !is_declaration_scope()) {
1017     return GetDeclarationScope()->DeclareVariable(
1018         declaration, mode, init, allow_harmony_restrictive_generators,
1019         sloppy_mode_block_scope_function_redefinition, ok);
1020   }
1021   DCHECK(!is_catch_scope());
1022   DCHECK(!is_with_scope());
1023   DCHECK(is_declaration_scope() ||
1024          (IsLexicalVariableMode(mode) && is_block_scope()));
1025 
1026   VariableProxy* proxy = declaration->proxy();
1027   DCHECK(proxy->raw_name() != NULL);
1028   const AstRawString* name = proxy->raw_name();
1029   bool is_function_declaration = declaration->IsFunctionDeclaration();
1030 
1031   // Pessimistically assume that top-level variables will be assigned.
1032   //
1033   // Top-level variables in a script can be accessed by other scripts or even
1034   // become global properties. While this does not apply to top-level variables
1035   // in a module (assuming they are not exported), we must still mark these as
1036   // assigned because they might be accessed by a lazily parsed top-level
1037   // function, which, for efficiency, we preparse without variable tracking.
1038   if (is_script_scope() || is_module_scope()) {
1039     if (mode != CONST) proxy->set_is_assigned();
1040   }
1041 
1042   Variable* var = nullptr;
1043   if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) {
1044     // In a var binding in a sloppy direct eval, pollute the enclosing scope
1045     // with this new binding by doing the following:
1046     // The proxy is bound to a lookup variable to force a dynamic declaration
1047     // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1048     var = new (zone())
1049         Variable(this, name, mode, NORMAL_VARIABLE, init, kMaybeAssigned);
1050     var->AllocateTo(VariableLocation::LOOKUP, -1);
1051   } else {
1052     // Declare the variable in the declaration scope.
1053     var = LookupLocal(name);
1054     if (var == NULL) {
1055       // Declare the name.
1056       VariableKind kind = NORMAL_VARIABLE;
1057       if (is_function_declaration) {
1058         kind = FUNCTION_VARIABLE;
1059       }
1060       var = DeclareLocal(name, mode, init, kind, kNotAssigned);
1061     } else if (IsLexicalVariableMode(mode) ||
1062                IsLexicalVariableMode(var->mode())) {
1063       // Allow duplicate function decls for web compat, see bug 4693.
1064       bool duplicate_allowed = false;
1065       if (is_sloppy(language_mode()) && is_function_declaration &&
1066           var->is_function()) {
1067         DCHECK(IsLexicalVariableMode(mode) &&
1068                IsLexicalVariableMode(var->mode()));
1069         // If the duplication is allowed, then the var will show up
1070         // in the SloppyBlockFunctionMap and the new FunctionKind
1071         // will be a permitted duplicate.
1072         FunctionKind function_kind =
1073             declaration->AsFunctionDeclaration()->fun()->kind();
1074         duplicate_allowed =
1075             GetDeclarationScope()->sloppy_block_function_map()->Lookup(
1076                 const_cast<AstRawString*>(name), name->hash()) != nullptr &&
1077             !IsAsyncFunction(function_kind) &&
1078             !(allow_harmony_restrictive_generators &&
1079               IsGeneratorFunction(function_kind));
1080       }
1081       if (duplicate_allowed) {
1082         *sloppy_mode_block_scope_function_redefinition = true;
1083       } else {
1084         // The name was declared in this scope before; check for conflicting
1085         // re-declarations. We have a conflict if either of the declarations
1086         // is not a var (in script scope, we also have to ignore legacy const
1087         // for compatibility). There is similar code in runtime.cc in the
1088         // Declare functions. The function CheckConflictingVarDeclarations
1089         // checks for var and let bindings from different scopes whereas this
1090         // is a check for conflicting declarations within the same scope. This
1091         // check also covers the special case
1092         //
1093         // function () { let x; { var x; } }
1094         //
1095         // because the var declaration is hoisted to the function scope where
1096         // 'x' is already bound.
1097         DCHECK(IsDeclaredVariableMode(var->mode()));
1098         // In harmony we treat re-declarations as early errors. See
1099         // ES5 16 for a definition of early errors.
1100         *ok = false;
1101         return nullptr;
1102       }
1103     } else if (mode == VAR) {
1104       var->set_maybe_assigned();
1105     }
1106   }
1107   DCHECK_NOT_NULL(var);
1108 
1109   // We add a declaration node for every declaration. The compiler
1110   // will only generate code if necessary. In particular, declarations
1111   // for inner local variables that do not represent functions won't
1112   // result in any generated code.
1113   //
1114   // This will lead to multiple declaration nodes for the
1115   // same variable if it is declared several times. This is not a
1116   // semantic issue, but it may be a performance issue since it may
1117   // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1118   decls_.Add(declaration);
1119   proxy->BindTo(var);
1120   return var;
1121 }
1122 
DeclareVariableName(const AstRawString * name,VariableMode mode)1123 Variable* Scope::DeclareVariableName(const AstRawString* name,
1124                                      VariableMode mode) {
1125   DCHECK(IsDeclaredVariableMode(mode));
1126   DCHECK(!already_resolved_);
1127   DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1128 
1129   if (mode == VAR && !is_declaration_scope()) {
1130     return GetDeclarationScope()->DeclareVariableName(name, mode);
1131   }
1132   DCHECK(!is_with_scope());
1133   DCHECK(!is_eval_scope());
1134   // Unlike DeclareVariable, DeclareVariableName allows declaring variables in
1135   // catch scopes: Parser::RewriteCatchPattern bypasses DeclareVariable by
1136   // calling DeclareLocal directly, and it doesn't make sense to add a similar
1137   // bypass mechanism for PreParser.
1138   DCHECK(is_declaration_scope() || (IsLexicalVariableMode(mode) &&
1139                                     (is_block_scope() || is_catch_scope())));
1140   DCHECK(scope_info_.is_null());
1141 
1142   // Declare the variable in the declaration scope.
1143   if (FLAG_preparser_scope_analysis) {
1144     Variable* var = LookupLocal(name);
1145     DCHECK_NE(var, kDummyPreParserLexicalVariable);
1146     DCHECK_NE(var, kDummyPreParserVariable);
1147     if (var == nullptr) {
1148       var = DeclareLocal(name, mode);
1149     } else if (mode == VAR) {
1150       DCHECK_EQ(var->mode(), VAR);
1151       var->set_maybe_assigned();
1152     }
1153     var->set_is_used();
1154     return var;
1155   } else {
1156     return variables_.DeclareName(zone(), name, mode);
1157   }
1158 }
1159 
NewUnresolved(AstNodeFactory * factory,const AstRawString * name,int start_position,VariableKind kind)1160 VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory,
1161                                     const AstRawString* name,
1162                                     int start_position, VariableKind kind) {
1163   // Note that we must not share the unresolved variables with
1164   // the same name because they may be removed selectively via
1165   // RemoveUnresolved().
1166   DCHECK(!already_resolved_);
1167   DCHECK_EQ(factory->zone(), zone());
1168   VariableProxy* proxy = factory->NewVariableProxy(name, kind, start_position);
1169   proxy->set_next_unresolved(unresolved_);
1170   unresolved_ = proxy;
1171   return proxy;
1172 }
1173 
AddUnresolved(VariableProxy * proxy)1174 void Scope::AddUnresolved(VariableProxy* proxy) {
1175   DCHECK(!already_resolved_);
1176   DCHECK(!proxy->is_resolved());
1177   proxy->set_next_unresolved(unresolved_);
1178   unresolved_ = proxy;
1179 }
1180 
DeclareDynamicGlobal(const AstRawString * name,VariableKind kind)1181 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1182                                                  VariableKind kind) {
1183   DCHECK(is_script_scope());
1184   return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind);
1185   // TODO(neis): Mark variable as maybe-assigned?
1186 }
1187 
1188 
RemoveUnresolved(VariableProxy * var)1189 bool Scope::RemoveUnresolved(VariableProxy* var) {
1190   if (unresolved_ == var) {
1191     unresolved_ = var->next_unresolved();
1192     var->set_next_unresolved(nullptr);
1193     return true;
1194   }
1195   VariableProxy* current = unresolved_;
1196   while (current != nullptr) {
1197     VariableProxy* next = current->next_unresolved();
1198     if (var == next) {
1199       current->set_next_unresolved(next->next_unresolved());
1200       var->set_next_unresolved(nullptr);
1201       return true;
1202     }
1203     current = next;
1204   }
1205   return false;
1206 }
1207 
NewTemporary(const AstRawString * name)1208 Variable* Scope::NewTemporary(const AstRawString* name) {
1209   return NewTemporary(name, kMaybeAssigned);
1210 }
1211 
NewTemporary(const AstRawString * name,MaybeAssignedFlag maybe_assigned)1212 Variable* Scope::NewTemporary(const AstRawString* name,
1213                               MaybeAssignedFlag maybe_assigned) {
1214   DeclarationScope* scope = GetClosureScope();
1215   Variable* var = new (zone())
1216       Variable(scope, name, TEMPORARY, NORMAL_VARIABLE, kCreatedInitialized);
1217   scope->AddLocal(var);
1218   if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1219   return var;
1220 }
1221 
CheckConflictingVarDeclarations()1222 Declaration* Scope::CheckConflictingVarDeclarations() {
1223   for (Declaration* decl : decls_) {
1224     VariableMode mode = decl->proxy()->var()->mode();
1225     if (IsLexicalVariableMode(mode) && !is_block_scope()) continue;
1226 
1227     // Iterate through all scopes until and including the declaration scope.
1228     Scope* previous = NULL;
1229     Scope* current = decl->scope();
1230     // Lexical vs lexical conflicts within the same scope have already been
1231     // captured in Parser::Declare. The only conflicts we still need to check
1232     // are lexical vs VAR, or any declarations within a declaration block scope
1233     // vs lexical declarations in its surrounding (function) scope.
1234     if (IsLexicalVariableMode(mode)) current = current->outer_scope_;
1235     do {
1236       // There is a conflict if there exists a non-VAR binding.
1237       Variable* other_var =
1238           current->variables_.Lookup(decl->proxy()->raw_name());
1239       if (other_var != NULL && IsLexicalVariableMode(other_var->mode())) {
1240         return decl;
1241       }
1242       previous = current;
1243       current = current->outer_scope_;
1244     } while (!previous->is_declaration_scope());
1245   }
1246   return NULL;
1247 }
1248 
CheckLexDeclarationsConflictingWith(const ZoneList<const AstRawString * > & names)1249 Declaration* Scope::CheckLexDeclarationsConflictingWith(
1250     const ZoneList<const AstRawString*>& names) {
1251   DCHECK(is_block_scope());
1252   for (int i = 0; i < names.length(); ++i) {
1253     Variable* var = LookupLocal(names.at(i));
1254     if (var != nullptr) {
1255       // Conflict; find and return its declaration.
1256       DCHECK(IsLexicalVariableMode(var->mode()));
1257       const AstRawString* name = names.at(i);
1258       for (Declaration* decl : decls_) {
1259         if (decl->proxy()->raw_name() == name) return decl;
1260       }
1261       DCHECK(false);
1262     }
1263   }
1264   return nullptr;
1265 }
1266 
AllocateVariables(ParseInfo * info,AnalyzeMode mode)1267 void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) {
1268   // Module variables must be allocated before variable resolution
1269   // to ensure that AccessNeedsHoleCheck() can detect import variables.
1270   if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1271 
1272   ResolveVariablesRecursively(info);
1273   AllocateVariablesRecursively();
1274 
1275   MaybeHandle<ScopeInfo> outer_scope;
1276   if (outer_scope_ != nullptr) outer_scope = outer_scope_->scope_info_;
1277 
1278   AllocateScopeInfosRecursively(info->isolate(), outer_scope);
1279   if (mode == AnalyzeMode::kDebugger) {
1280     AllocateDebuggerScopeInfos(info->isolate(), outer_scope);
1281   }
1282   // The debugger expects all shared function infos to contain a scope info.
1283   // Since the top-most scope will end up in a shared function info, make sure
1284   // it has one, even if it doesn't need a scope info.
1285   // TODO(jochen|yangguo): Remove this requirement.
1286   if (scope_info_.is_null()) {
1287     scope_info_ = ScopeInfo::Create(info->isolate(), zone(), this, outer_scope);
1288   }
1289 }
1290 
AllowsLazyParsingWithoutUnresolvedVariables(const Scope * outer) const1291 bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1292     const Scope* outer) const {
1293   // If none of the outer scopes need to decide whether to context allocate
1294   // specific variables, we can preparse inner functions without unresolved
1295   // variables. Otherwise we need to find unresolved variables to force context
1296   // allocation of the matching declarations. We can stop at the outer scope for
1297   // the parse, since context allocation of those variables is already
1298   // guaranteed to be correct.
1299   for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1300     // Eval forces context allocation on all outer scopes, so we don't need to
1301     // look at those scopes. Sloppy eval makes top-level non-lexical variables
1302     // dynamic, whereas strict-mode requires context allocation.
1303     if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1304     // Catch scopes force context allocation of all variables.
1305     if (s->is_catch_scope()) continue;
1306     // With scopes do not introduce variables that need allocation.
1307     if (s->is_with_scope()) continue;
1308     // If everything is guaranteed to be context allocated we can ignore the
1309     // scope.
1310     if (s->has_forced_context_allocation()) continue;
1311     // Only block scopes and function scopes should disallow preparsing.
1312     DCHECK(s->is_block_scope() || s->is_function_scope());
1313     return false;
1314   }
1315   return true;
1316 }
1317 
AllowsLazyCompilation() const1318 bool DeclarationScope::AllowsLazyCompilation() const {
1319   return !force_eager_compilation_;
1320 }
1321 
ContextChainLength(Scope * scope) const1322 int Scope::ContextChainLength(Scope* scope) const {
1323   int n = 0;
1324   for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1325     DCHECK(s != NULL);  // scope must be in the scope chain
1326     if (s->NeedsContext()) n++;
1327   }
1328   return n;
1329 }
1330 
ContextChainLengthUntilOutermostSloppyEval() const1331 int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1332   int result = 0;
1333   int length = 0;
1334 
1335   for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1336     if (!s->NeedsContext()) continue;
1337     length++;
1338     if (s->calls_sloppy_eval()) result = length;
1339   }
1340 
1341   return result;
1342 }
1343 
MaxNestedContextChainLength()1344 int Scope::MaxNestedContextChainLength() {
1345   int max_context_chain_length = 0;
1346   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1347     if (scope->is_function_scope()) continue;
1348     max_context_chain_length = std::max(scope->MaxNestedContextChainLength(),
1349                                         max_context_chain_length);
1350   }
1351   if (NeedsContext()) {
1352     max_context_chain_length += 1;
1353   }
1354   return max_context_chain_length;
1355 }
1356 
GetDeclarationScope()1357 DeclarationScope* Scope::GetDeclarationScope() {
1358   Scope* scope = this;
1359   while (!scope->is_declaration_scope()) {
1360     scope = scope->outer_scope();
1361   }
1362   return scope->AsDeclarationScope();
1363 }
1364 
GetClosureScope() const1365 const DeclarationScope* Scope::GetClosureScope() const {
1366   const Scope* scope = this;
1367   while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1368     scope = scope->outer_scope();
1369   }
1370   return scope->AsDeclarationScope();
1371 }
1372 
GetClosureScope()1373 DeclarationScope* Scope::GetClosureScope() {
1374   Scope* scope = this;
1375   while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1376     scope = scope->outer_scope();
1377   }
1378   return scope->AsDeclarationScope();
1379 }
1380 
NeedsScopeInfo() const1381 bool Scope::NeedsScopeInfo() const {
1382   DCHECK(!already_resolved_);
1383   DCHECK(GetClosureScope()->ShouldEagerCompile());
1384   // The debugger expects all functions to have scope infos.
1385   // TODO(jochen|yangguo): Remove this requirement.
1386   if (is_function_scope()) return true;
1387   return NeedsContext();
1388 }
1389 
GetModuleScope()1390 ModuleScope* Scope::GetModuleScope() {
1391   Scope* scope = this;
1392   DCHECK(!scope->is_script_scope());
1393   while (!scope->is_module_scope()) {
1394     scope = scope->outer_scope();
1395     DCHECK_NOT_NULL(scope);
1396   }
1397   return scope->AsModuleScope();
1398 }
1399 
GetReceiverScope()1400 DeclarationScope* Scope::GetReceiverScope() {
1401   Scope* scope = this;
1402   while (!scope->is_script_scope() &&
1403          (!scope->is_function_scope() ||
1404           scope->AsDeclarationScope()->is_arrow_scope())) {
1405     scope = scope->outer_scope();
1406   }
1407   return scope->AsDeclarationScope();
1408 }
1409 
GetOuterScopeWithContext()1410 Scope* Scope::GetOuterScopeWithContext() {
1411   Scope* scope = outer_scope_;
1412   while (scope && !scope->NeedsContext()) {
1413     scope = scope->outer_scope();
1414   }
1415   return scope;
1416 }
1417 
CollectNonLocals(ParseInfo * info,Handle<StringSet> non_locals)1418 Handle<StringSet> DeclarationScope::CollectNonLocals(
1419     ParseInfo* info, Handle<StringSet> non_locals) {
1420   VariableProxy* free_variables = FetchFreeVariables(this, info);
1421   for (VariableProxy* proxy = free_variables; proxy != nullptr;
1422        proxy = proxy->next_unresolved()) {
1423     non_locals = StringSet::Add(non_locals, proxy->name());
1424   }
1425   return non_locals;
1426 }
1427 
ResetAfterPreparsing(AstValueFactory * ast_value_factory,bool aborted)1428 void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1429                                             bool aborted) {
1430   DCHECK(is_function_scope());
1431 
1432   // Reset all non-trivial members.
1433   if (!aborted || !IsArrowFunction(function_kind_)) {
1434     // Do not remove parameters when lazy parsing an Arrow Function has failed,
1435     // as the formal parameters are not re-parsed.
1436     params_.Clear();
1437   }
1438   decls_.Clear();
1439   locals_.Clear();
1440   inner_scope_ = nullptr;
1441   unresolved_ = nullptr;
1442 
1443   if (aborted) {
1444     // Prepare scope for use in the outer zone.
1445     zone_ = ast_value_factory->zone();
1446     variables_.Reset(ZoneAllocationPolicy(zone_));
1447     sloppy_block_function_map_.Reset(ZoneAllocationPolicy(zone_));
1448     if (!IsArrowFunction(function_kind_)) {
1449       DeclareDefaultFunctionVariables(ast_value_factory);
1450     }
1451   } else {
1452     // Make sure this scope isn't used for allocation anymore.
1453     zone_ = nullptr;
1454     variables_.Invalidate();
1455     sloppy_block_function_map_.Invalidate();
1456   }
1457 
1458 #ifdef DEBUG
1459   needs_migration_ = false;
1460   is_being_lazily_parsed_ = false;
1461 #endif
1462 
1463   was_lazily_parsed_ = !aborted;
1464 }
1465 
AnalyzePartially(AstNodeFactory * ast_node_factory,PreParsedScopeData * preparsed_scope_data)1466 void DeclarationScope::AnalyzePartially(
1467     AstNodeFactory* ast_node_factory,
1468     PreParsedScopeData* preparsed_scope_data) {
1469   DCHECK(!force_eager_compilation_);
1470   VariableProxy* unresolved = nullptr;
1471 
1472   if (!outer_scope_->is_script_scope()) {
1473     // Try to resolve unresolved variables for this Scope and migrate those
1474     // which cannot be resolved inside. It doesn't make sense to try to resolve
1475     // them in the outer Scopes here, because they are incomplete.
1476     for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr;
1477          proxy = proxy->next_unresolved()) {
1478       DCHECK(!proxy->is_resolved());
1479       VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1480       copy->set_next_unresolved(unresolved);
1481       unresolved = copy;
1482     }
1483 
1484     // Clear arguments_ if unused. This is used as a signal for optimization.
1485     if (arguments_ != nullptr &&
1486         !(MustAllocate(arguments_) && !has_arguments_parameter_)) {
1487       arguments_ = nullptr;
1488     }
1489 
1490     if (FLAG_preparser_scope_analysis) {
1491       // Decide context allocation for the locals and parameters and store the
1492       // info away.
1493       AllocateVariablesRecursively();
1494       CollectVariableData(preparsed_scope_data);
1495     }
1496   }
1497 #ifdef DEBUG
1498   if (FLAG_print_scopes) {
1499     PrintF("Inner function scope:\n");
1500     Print();
1501   }
1502 #endif
1503 
1504   ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1505 
1506   unresolved_ = unresolved;
1507 }
1508 
1509 #ifdef DEBUG
1510 namespace {
1511 
Header(ScopeType scope_type,FunctionKind function_kind,bool is_declaration_scope)1512 const char* Header(ScopeType scope_type, FunctionKind function_kind,
1513                    bool is_declaration_scope) {
1514   switch (scope_type) {
1515     case EVAL_SCOPE: return "eval";
1516     // TODO(adamk): Should we print concise method scopes specially?
1517     case FUNCTION_SCOPE:
1518       if (IsGeneratorFunction(function_kind)) return "function*";
1519       if (IsAsyncFunction(function_kind)) return "async function";
1520       if (IsArrowFunction(function_kind)) return "arrow";
1521       return "function";
1522     case MODULE_SCOPE: return "module";
1523     case SCRIPT_SCOPE: return "global";
1524     case CATCH_SCOPE: return "catch";
1525     case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1526     case WITH_SCOPE: return "with";
1527   }
1528   UNREACHABLE();
1529   return NULL;
1530 }
1531 
Indent(int n,const char * str)1532 void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1533 
PrintName(const AstRawString * name)1534 void PrintName(const AstRawString* name) {
1535   PrintF("%.*s", name->length(), name->raw_data());
1536 }
1537 
PrintLocation(Variable * var)1538 void PrintLocation(Variable* var) {
1539   switch (var->location()) {
1540     case VariableLocation::UNALLOCATED:
1541       break;
1542     case VariableLocation::PARAMETER:
1543       PrintF("parameter[%d]", var->index());
1544       break;
1545     case VariableLocation::LOCAL:
1546       PrintF("local[%d]", var->index());
1547       break;
1548     case VariableLocation::CONTEXT:
1549       PrintF("context[%d]", var->index());
1550       break;
1551     case VariableLocation::LOOKUP:
1552       PrintF("lookup");
1553       break;
1554     case VariableLocation::MODULE:
1555       PrintF("module");
1556       break;
1557   }
1558 }
1559 
PrintVar(int indent,Variable * var)1560 void PrintVar(int indent, Variable* var) {
1561   Indent(indent, VariableMode2String(var->mode()));
1562   PrintF(" ");
1563   if (var->raw_name()->IsEmpty())
1564     PrintF(".%p", reinterpret_cast<void*>(var));
1565   else
1566     PrintName(var->raw_name());
1567   PrintF(";  // ");
1568   PrintLocation(var);
1569   bool comma = !var->IsUnallocated();
1570   if (var->has_forced_context_allocation()) {
1571     if (comma) PrintF(", ");
1572     PrintF("forced context allocation");
1573     comma = true;
1574   }
1575   if (var->maybe_assigned() == kNotAssigned) {
1576     if (comma) PrintF(", ");
1577     PrintF("never assigned");
1578   }
1579   PrintF("\n");
1580 }
1581 
PrintMap(int indent,const char * label,VariableMap * map,bool locals,Variable * function_var)1582 void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1583               Variable* function_var) {
1584   bool printed_label = false;
1585   for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1586     Variable* var = reinterpret_cast<Variable*>(p->value);
1587     if (var == function_var) continue;
1588     if (var == kDummyPreParserVariable ||
1589         var == kDummyPreParserLexicalVariable) {
1590       continue;
1591     }
1592     bool local = !IsDynamicVariableMode(var->mode());
1593     if ((locals ? local : !local) &&
1594         (var->is_used() || !var->IsUnallocated())) {
1595       if (!printed_label) {
1596         Indent(indent, label);
1597         printed_label = true;
1598       }
1599       PrintVar(indent, var);
1600     }
1601   }
1602 }
1603 
1604 }  // anonymous namespace
1605 
PrintParameters()1606 void DeclarationScope::PrintParameters() {
1607   PrintF(" (");
1608   for (int i = 0; i < params_.length(); i++) {
1609     if (i > 0) PrintF(", ");
1610     const AstRawString* name = params_[i]->raw_name();
1611     if (name->IsEmpty())
1612       PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1613     else
1614       PrintName(name);
1615   }
1616   PrintF(")");
1617 }
1618 
Print(int n)1619 void Scope::Print(int n) {
1620   int n0 = (n > 0 ? n : 0);
1621   int n1 = n0 + 2;  // indentation
1622 
1623   // Print header.
1624   FunctionKind function_kind = is_function_scope()
1625                                    ? AsDeclarationScope()->function_kind()
1626                                    : kNormalFunction;
1627   Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1628   if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1629     PrintF(" ");
1630     PrintName(scope_name_);
1631   }
1632 
1633   // Print parameters, if any.
1634   Variable* function = nullptr;
1635   if (is_function_scope()) {
1636     AsDeclarationScope()->PrintParameters();
1637     function = AsDeclarationScope()->function_var();
1638   }
1639 
1640   PrintF(" { // (%d, %d)\n", start_position(), end_position());
1641   if (is_hidden()) {
1642     Indent(n1, "// is hidden\n");
1643   }
1644 
1645   // Function name, if any (named function literals, only).
1646   if (function != nullptr) {
1647     Indent(n1, "// (local) function name: ");
1648     PrintName(function->raw_name());
1649     PrintF("\n");
1650   }
1651 
1652   // Scope info.
1653   if (is_strict(language_mode())) {
1654     Indent(n1, "// strict mode scope\n");
1655   }
1656   if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1657   if (IsAsmFunction()) Indent(n1, "// scope is an asm function\n");
1658   if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
1659   if (is_declaration_scope() && AsDeclarationScope()->uses_super_property()) {
1660     Indent(n1, "// scope uses 'super' property\n");
1661   }
1662   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1663   if (is_declaration_scope()) {
1664     DeclarationScope* scope = AsDeclarationScope();
1665     if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1666     if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1667   }
1668   if (has_forced_context_allocation()) {
1669     Indent(n1, "// forces context allocation\n");
1670   }
1671   if (num_stack_slots_ > 0) {
1672     Indent(n1, "// ");
1673     PrintF("%d stack slots\n", num_stack_slots_);
1674   }
1675   if (num_heap_slots_ > 0) {
1676     Indent(n1, "// ");
1677     PrintF("%d heap slots\n", num_heap_slots_);
1678   }
1679 
1680   // Print locals.
1681   if (function != nullptr) {
1682     Indent(n1, "// function var:\n");
1683     PrintVar(n1, function);
1684   }
1685 
1686   // Print temporaries.
1687   {
1688     bool printed_header = false;
1689     for (Variable* local : locals_) {
1690       if (local->mode() != TEMPORARY) continue;
1691       if (!printed_header) {
1692         printed_header = true;
1693         Indent(n1, "// temporary vars:\n");
1694       }
1695       PrintVar(n1, local);
1696     }
1697   }
1698 
1699   if (variables_.occupancy() > 0) {
1700     PrintMap(n1, "// local vars:\n", &variables_, true, function);
1701     PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1702   }
1703 
1704   // Print inner scopes (disable by providing negative n).
1705   if (n >= 0) {
1706     for (Scope* scope = inner_scope_; scope != nullptr;
1707          scope = scope->sibling_) {
1708       PrintF("\n");
1709       scope->Print(n1);
1710     }
1711   }
1712 
1713   Indent(n0, "}\n");
1714 }
1715 
CheckScopePositions()1716 void Scope::CheckScopePositions() {
1717   // Visible leaf scopes must have real positions.
1718   if (!is_hidden() && inner_scope_ == nullptr) {
1719     CHECK_NE(kNoSourcePosition, start_position());
1720     CHECK_NE(kNoSourcePosition, end_position());
1721   }
1722   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1723     scope->CheckScopePositions();
1724   }
1725 }
1726 
CheckZones()1727 void Scope::CheckZones() {
1728   DCHECK(!needs_migration_);
1729   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1730     if (scope->is_declaration_scope() &&
1731         scope->AsDeclarationScope()->was_lazily_parsed()) {
1732       DCHECK_NULL(scope->zone());
1733       DCHECK_NULL(scope->inner_scope_);
1734       continue;
1735     }
1736     CHECK_EQ(scope->zone(), zone());
1737     scope->CheckZones();
1738   }
1739 }
1740 #endif  // DEBUG
1741 
NonLocal(const AstRawString * name,VariableMode mode)1742 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1743   // Declare a new non-local.
1744   DCHECK(IsDynamicVariableMode(mode));
1745   Variable* var = variables_.Declare(zone(), nullptr, name, mode);
1746   // Allocate it by giving it a dynamic lookup.
1747   var->AllocateTo(VariableLocation::LOOKUP, -1);
1748   return var;
1749 }
1750 
LookupRecursive(VariableProxy * proxy,Scope * outer_scope_end)1751 Variable* Scope::LookupRecursive(VariableProxy* proxy, Scope* outer_scope_end) {
1752   DCHECK_NE(outer_scope_end, this);
1753   // Short-cut: whenever we find a debug-evaluate scope, just look everything up
1754   // dynamically. Debug-evaluate doesn't properly create scope info for the
1755   // lookups it does. It may not have a valid 'this' declaration, and anything
1756   // accessed through debug-evaluate might invalidly resolve to stack-allocated
1757   // variables.
1758   // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the
1759   // scopes in which it's evaluating.
1760   if (is_debug_evaluate_scope_) return NonLocal(proxy->raw_name(), DYNAMIC);
1761 
1762   // Try to find the variable in this scope.
1763   Variable* var = LookupLocal(proxy->raw_name());
1764 
1765   // We found a variable and we are done. (Even if there is an 'eval' in this
1766   // scope which introduces the same variable again, the resulting variable
1767   // remains the same.)
1768   if (var != nullptr) return var;
1769 
1770   if (outer_scope_ == outer_scope_end) {
1771     // We may just be trying to find all free variables. In that case, don't
1772     // declare them in the outer scope.
1773     if (!is_script_scope()) return nullptr;
1774     // No binding has been found. Declare a variable on the global object.
1775     return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(),
1776                                                       NORMAL_VARIABLE);
1777   }
1778 
1779   DCHECK(!is_script_scope());
1780 
1781   var = outer_scope_->LookupRecursive(proxy, outer_scope_end);
1782 
1783   // The variable could not be resolved statically.
1784   if (var == nullptr) return var;
1785 
1786   // TODO(marja): Separate LookupRecursive for preparsed scopes better.
1787   if (var == kDummyPreParserVariable || var == kDummyPreParserLexicalVariable) {
1788     DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
1789     DCHECK(FLAG_lazy_inner_functions);
1790     return var;
1791   }
1792 
1793   if (is_function_scope() && !var->is_dynamic()) {
1794     var->ForceContextAllocation();
1795   }
1796   // "this" can't be shadowed by "eval"-introduced bindings or by "with"
1797   // scopes.
1798   // TODO(wingo): There are other variables in this category; add them.
1799   if (var->is_this()) return var;
1800 
1801   if (is_with_scope()) {
1802     // The current scope is a with scope, so the variable binding can not be
1803     // statically resolved. However, note that it was necessary to do a lookup
1804     // in the outer scope anyway, because if a binding exists in an outer
1805     // scope, the associated variable has to be marked as potentially being
1806     // accessed from inside of an inner with scope (the property may not be in
1807     // the 'with' object).
1808     if (!var->is_dynamic() && var->IsUnallocated()) {
1809       DCHECK(!already_resolved_);
1810       var->set_is_used();
1811       var->ForceContextAllocation();
1812       if (proxy->is_assigned()) var->set_maybe_assigned();
1813     }
1814     return NonLocal(proxy->raw_name(), DYNAMIC);
1815   }
1816 
1817   if (calls_sloppy_eval() && is_declaration_scope()) {
1818     // A variable binding may have been found in an outer scope, but the current
1819     // scope makes a sloppy 'eval' call, so the found variable may not be the
1820     // correct one (the 'eval' may introduce a binding with the same name). In
1821     // that case, change the lookup result to reflect this situation. Only
1822     // scopes that can host var bindings (declaration scopes) need be considered
1823     // here (this excludes block and catch scopes), and variable lookups at
1824     // script scope are always dynamic.
1825     if (var->IsGlobalObjectProperty()) {
1826       return NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1827     }
1828 
1829     if (var->is_dynamic()) return var;
1830 
1831     Variable* invalidated = var;
1832     var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
1833     var->set_local_if_not_shadowed(invalidated);
1834   }
1835 
1836   return var;
1837 }
1838 
ResolveVariable(ParseInfo * info,VariableProxy * proxy)1839 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1840   DCHECK(info->script_scope()->is_script_scope());
1841   DCHECK(!proxy->is_resolved());
1842   Variable* var = LookupRecursive(proxy, nullptr);
1843   ResolveTo(info, proxy, var);
1844 }
1845 
1846 namespace {
1847 
AccessNeedsHoleCheck(Variable * var,VariableProxy * proxy,Scope * scope)1848 bool AccessNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1849   if (var->mode() == DYNAMIC_LOCAL) {
1850     // Dynamically introduced variables never need a hole check (since they're
1851     // VAR bindings, either from var or function declarations), but the variable
1852     // they shadow might need a hole check, which we want to do if we decide
1853     // that no shadowing variable was dynamically introoduced.
1854     DCHECK(!var->binding_needs_init());
1855     return AccessNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
1856   }
1857 
1858   if (!var->binding_needs_init()) {
1859     return false;
1860   }
1861 
1862   // It's impossible to eliminate module import hole checks here, because it's
1863   // unknown at compilation time whether the binding referred to in the
1864   // exporting module itself requires hole checks.
1865   if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
1866     return true;
1867   }
1868 
1869   // Check if the binding really needs an initialization check. The check
1870   // can be skipped in the following situation: we have a LET or CONST
1871   // binding, both the Variable and the VariableProxy have the same
1872   // declaration scope (i.e. they are both in global code, in the
1873   // same function or in the same eval code), the VariableProxy is in
1874   // the source physically located after the initializer of the variable,
1875   // and that the initializer cannot be skipped due to a nonlinear scope.
1876   //
1877   // The condition on the declaration scopes is a conservative check for
1878   // nested functions that access a binding and are called before the
1879   // binding is initialized:
1880   //   function() { f(); let x = 1; function f() { x = 2; } }
1881   //
1882   // The check cannot be skipped on non-linear scopes, namely switch
1883   // scopes, to ensure tests are done in cases like the following:
1884   //   switch (1) { case 0: let x = 2; case 1: f(x); }
1885   // The scope of the variable needs to be checked, in case the use is
1886   // in a sub-block which may be linear.
1887   if (var->scope()->GetDeclarationScope() != scope->GetDeclarationScope()) {
1888     return true;
1889   }
1890 
1891   if (var->is_this()) {
1892     DCHECK(IsDerivedConstructor(scope->GetDeclarationScope()->function_kind()));
1893     // TODO(littledan): implement 'this' hole check elimination.
1894     return true;
1895   }
1896 
1897   // We should always have valid source positions.
1898   DCHECK(var->initializer_position() != kNoSourcePosition);
1899   DCHECK(proxy->position() != kNoSourcePosition);
1900 
1901   return var->scope()->is_nonlinear() ||
1902          var->initializer_position() >= proxy->position();
1903 }
1904 
1905 }  // anonymous namespace
1906 
ResolveTo(ParseInfo * info,VariableProxy * proxy,Variable * var)1907 void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1908 #ifdef DEBUG
1909   if (info->script_is_native()) {
1910     // To avoid polluting the global object in native scripts
1911     //  - Variables must not be allocated to the global scope.
1912     CHECK_NOT_NULL(outer_scope());
1913     //  - Variables must be bound locally or unallocated.
1914     if (var->IsGlobalObjectProperty()) {
1915       // The following variable name may be minified. If so, disable
1916       // minification in js2c.py for better output.
1917       Handle<String> name = proxy->raw_name()->string();
1918       V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.",
1919                name->ToCString().get());
1920     }
1921     VariableLocation location = var->location();
1922     CHECK(location == VariableLocation::LOCAL ||
1923           location == VariableLocation::CONTEXT ||
1924           location == VariableLocation::PARAMETER ||
1925           location == VariableLocation::UNALLOCATED);
1926   }
1927 #endif
1928 
1929   DCHECK_NOT_NULL(var);
1930   if (AccessNeedsHoleCheck(var, proxy, this)) proxy->set_needs_hole_check();
1931   proxy->BindTo(var);
1932 }
1933 
ResolveVariablesRecursively(ParseInfo * info)1934 void Scope::ResolveVariablesRecursively(ParseInfo* info) {
1935   DCHECK(info->script_scope()->is_script_scope());
1936   // Lazy parsed declaration scopes are already partially analyzed. If there are
1937   // unresolved references remaining, they just need to be resolved in outer
1938   // scopes.
1939   if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
1940     DCHECK(variables_.occupancy() == 0);
1941     for (VariableProxy* proxy = unresolved_; proxy != nullptr;
1942          proxy = proxy->next_unresolved()) {
1943       Variable* var = outer_scope()->LookupRecursive(proxy, nullptr);
1944       if (!var->is_dynamic()) {
1945         var->set_is_used();
1946         var->ForceContextAllocation();
1947         if (proxy->is_assigned()) var->set_maybe_assigned();
1948       }
1949     }
1950   } else {
1951     // Resolve unresolved variables for this scope.
1952     for (VariableProxy* proxy = unresolved_; proxy != nullptr;
1953          proxy = proxy->next_unresolved()) {
1954       ResolveVariable(info, proxy);
1955     }
1956 
1957     // Resolve unresolved variables for inner scopes.
1958     for (Scope* scope = inner_scope_; scope != nullptr;
1959          scope = scope->sibling_) {
1960       scope->ResolveVariablesRecursively(info);
1961     }
1962   }
1963 }
1964 
FetchFreeVariables(DeclarationScope * max_outer_scope,ParseInfo * info,VariableProxy * stack)1965 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
1966                                          ParseInfo* info,
1967                                          VariableProxy* stack) {
1968   // Module variables must be allocated before variable resolution
1969   // to ensure that AccessNeedsHoleCheck() can detect import variables.
1970   if (info != nullptr && is_module_scope()) {
1971     AsModuleScope()->AllocateModuleVariables();
1972   }
1973   // Lazy parsed declaration scopes are already partially analyzed. If there are
1974   // unresolved references remaining, they just need to be resolved in outer
1975   // scopes.
1976   Scope* lookup =
1977       is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()
1978           ? outer_scope()
1979           : this;
1980   for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
1981        proxy = next) {
1982     next = proxy->next_unresolved();
1983     DCHECK(!proxy->is_resolved());
1984     Variable* var =
1985         lookup->LookupRecursive(proxy, max_outer_scope->outer_scope());
1986     if (var == nullptr) {
1987       proxy->set_next_unresolved(stack);
1988       stack = proxy;
1989     } else if (var != kDummyPreParserVariable &&
1990                var != kDummyPreParserLexicalVariable) {
1991       if (info != nullptr) {
1992         // In this case we need to leave scopes in a way that they can be
1993         // allocated. If we resolved variables from lazy parsed scopes, we need
1994         // to context allocate the var.
1995         ResolveTo(info, proxy, var);
1996         if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation();
1997       } else {
1998         var->set_is_used();
1999         if (proxy->is_assigned()) {
2000           var->set_maybe_assigned();
2001         }
2002       }
2003     }
2004   }
2005 
2006   // Clear unresolved_ as it's in an inconsistent state.
2007   unresolved_ = nullptr;
2008 
2009   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2010     stack = scope->FetchFreeVariables(max_outer_scope, info, stack);
2011   }
2012 
2013   return stack;
2014 }
2015 
MustAllocate(Variable * var)2016 bool Scope::MustAllocate(Variable* var) {
2017   if (var == kDummyPreParserLexicalVariable || var == kDummyPreParserVariable) {
2018     return true;
2019   }
2020   DCHECK(var->location() != VariableLocation::MODULE);
2021   // Give var a read/write use if there is a chance it might be accessed
2022   // via an eval() call.  This is only possible if the variable has a
2023   // visible name.
2024   if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
2025       (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2026     var->set_is_used();
2027     if (inner_scope_calls_eval_) var->set_maybe_assigned();
2028   }
2029   DCHECK(!var->has_forced_context_allocation() || var->is_used());
2030   // Global variables do not need to be allocated.
2031   return !var->IsGlobalObjectProperty() && var->is_used();
2032 }
2033 
2034 
MustAllocateInContext(Variable * var)2035 bool Scope::MustAllocateInContext(Variable* var) {
2036   // If var is accessed from an inner scope, or if there is a possibility
2037   // that it might be accessed from the current or an inner scope (through
2038   // an eval() call or a runtime with lookup), it must be allocated in the
2039   // context.
2040   //
2041   // Exceptions: If the scope as a whole has forced context allocation, all
2042   // variables will have context allocation, even temporaries.  Otherwise
2043   // temporary variables are always stack-allocated.  Catch-bound variables are
2044   // always context-allocated.
2045   if (has_forced_context_allocation()) return true;
2046   if (var->mode() == TEMPORARY) return false;
2047   if (is_catch_scope()) return true;
2048   if ((is_script_scope() || is_eval_scope()) &&
2049       IsLexicalVariableMode(var->mode())) {
2050     return true;
2051   }
2052   return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2053 }
2054 
2055 
AllocateStackSlot(Variable * var)2056 void Scope::AllocateStackSlot(Variable* var) {
2057   if (is_block_scope()) {
2058     outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2059   } else {
2060     var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2061   }
2062 }
2063 
2064 
AllocateHeapSlot(Variable * var)2065 void Scope::AllocateHeapSlot(Variable* var) {
2066   var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2067 }
2068 
AllocateParameterLocals()2069 void DeclarationScope::AllocateParameterLocals() {
2070   DCHECK(is_function_scope());
2071 
2072   bool uses_sloppy_arguments = false;
2073 
2074   if (arguments_ != nullptr) {
2075     DCHECK(!is_arrow_scope());
2076     // 'arguments' is used. Unless there is also a parameter called
2077     // 'arguments', we must be conservative and allocate all parameters to
2078     // the context assuming they will be captured by the arguments object.
2079     // If we have a parameter named 'arguments', a (new) value is always
2080     // assigned to it via the function invocation. Then 'arguments' denotes
2081     // that specific parameter value and cannot be used to access the
2082     // parameters, which is why we don't need to allocate an arguments
2083     // object in that case.
2084     if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2085       // In strict mode 'arguments' does not alias formal parameters.
2086       // Therefore in strict mode we allocate parameters as if 'arguments'
2087       // were not used.
2088       // If the parameter list is not simple, arguments isn't sloppy either.
2089       uses_sloppy_arguments =
2090           is_sloppy(language_mode()) && has_simple_parameters();
2091     } else {
2092       // 'arguments' is unused. Tell the code generator that it does not need to
2093       // allocate the arguments object by nulling out arguments_.
2094       arguments_ = nullptr;
2095     }
2096   }
2097 
2098   // The same parameter may occur multiple times in the parameters_ list.
2099   // If it does, and if it is not copied into the context object, it must
2100   // receive the highest parameter index for that parameter; thus iteration
2101   // order is relevant!
2102   for (int i = num_parameters() - 1; i >= 0; --i) {
2103     Variable* var = params_[i];
2104     DCHECK(!has_rest_ || var != rest_parameter());
2105     DCHECK_EQ(this, var->scope());
2106     if (uses_sloppy_arguments) {
2107       var->set_is_used();
2108       var->set_maybe_assigned();
2109       var->ForceContextAllocation();
2110     }
2111     AllocateParameter(var, i);
2112   }
2113 }
2114 
AllocateParameter(Variable * var,int index)2115 void DeclarationScope::AllocateParameter(Variable* var, int index) {
2116   if (MustAllocate(var)) {
2117     if (MustAllocateInContext(var)) {
2118       DCHECK(var->IsUnallocated() || var->IsContextSlot());
2119       if (var->IsUnallocated()) {
2120         AllocateHeapSlot(var);
2121       }
2122     } else {
2123       DCHECK(var->IsUnallocated() || var->IsParameter());
2124       if (var->IsUnallocated()) {
2125         var->AllocateTo(VariableLocation::PARAMETER, index);
2126       }
2127     }
2128   }
2129 }
2130 
AllocateReceiver()2131 void DeclarationScope::AllocateReceiver() {
2132   if (!has_this_declaration()) return;
2133   DCHECK_NOT_NULL(receiver());
2134   DCHECK_EQ(receiver()->scope(), this);
2135   AllocateParameter(receiver(), -1);
2136 }
2137 
AllocateNonParameterLocal(Variable * var)2138 void Scope::AllocateNonParameterLocal(Variable* var) {
2139   DCHECK(var->scope() == this);
2140   if (var->IsUnallocated() && MustAllocate(var)) {
2141     if (MustAllocateInContext(var)) {
2142       AllocateHeapSlot(var);
2143     } else {
2144       AllocateStackSlot(var);
2145     }
2146   }
2147 }
2148 
AllocateNonParameterLocalsAndDeclaredGlobals()2149 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2150   for (Variable* local : locals_) {
2151     AllocateNonParameterLocal(local);
2152   }
2153 
2154   if (is_declaration_scope()) {
2155     AsDeclarationScope()->AllocateLocals();
2156   }
2157 }
2158 
AllocateLocals()2159 void DeclarationScope::AllocateLocals() {
2160   // For now, function_ must be allocated at the very end.  If it gets
2161   // allocated in the context, it must be the last slot in the context,
2162   // because of the current ScopeInfo implementation (see
2163   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2164   if (function_ != nullptr) {
2165     AllocateNonParameterLocal(function_);
2166   }
2167 
2168   DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2169          !rest_parameter()->IsUnallocated());
2170 
2171   if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2172     new_target_ = nullptr;
2173   }
2174 
2175   NullifyRareVariableIf(RareVariable::kThisFunction,
2176                         [=](Variable* var) { return !MustAllocate(var); });
2177 }
2178 
AllocateModuleVariables()2179 void ModuleScope::AllocateModuleVariables() {
2180   for (const auto& it : module()->regular_imports()) {
2181     Variable* var = LookupLocal(it.first);
2182     var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2183     DCHECK(!var->IsExport());
2184   }
2185 
2186   for (const auto& it : module()->regular_exports()) {
2187     Variable* var = LookupLocal(it.first);
2188     var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2189     DCHECK(var->IsExport());
2190   }
2191 }
2192 
AllocateVariablesRecursively()2193 void Scope::AllocateVariablesRecursively() {
2194   DCHECK(!already_resolved_);
2195   DCHECK_IMPLIES(!FLAG_preparser_scope_analysis, num_stack_slots_ == 0);
2196 
2197   // Don't allocate variables of preparsed scopes.
2198   if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) {
2199     return;
2200   }
2201 
2202   // Allocate variables for inner scopes.
2203   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2204     scope->AllocateVariablesRecursively();
2205   }
2206 
2207   DCHECK(!already_resolved_);
2208   DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
2209 
2210   // Allocate variables for this scope.
2211   // Parameters must be allocated first, if any.
2212   if (is_declaration_scope()) {
2213     if (is_function_scope()) {
2214       AsDeclarationScope()->AllocateParameterLocals();
2215     }
2216     AsDeclarationScope()->AllocateReceiver();
2217   }
2218   AllocateNonParameterLocalsAndDeclaredGlobals();
2219 
2220   // Force allocation of a context for this scope if necessary. For a 'with'
2221   // scope and for a function scope that makes an 'eval' call we need a context,
2222   // even if no local variables were statically allocated in the scope.
2223   // Likewise for modules and function scopes representing asm.js modules.
2224   bool must_have_context =
2225       is_with_scope() || is_module_scope() || IsAsmModule() ||
2226       (is_function_scope() && calls_sloppy_eval()) ||
2227       (is_block_scope() && is_declaration_scope() && calls_sloppy_eval());
2228 
2229   // If we didn't allocate any locals in the local context, then we only
2230   // need the minimal number of slots if we must have a context.
2231   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
2232     num_heap_slots_ = 0;
2233   }
2234 
2235   // Allocation done.
2236   DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2237 }
2238 
AllocateScopeInfosRecursively(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)2239 void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
2240                                           MaybeHandle<ScopeInfo> outer_scope) {
2241   DCHECK(scope_info_.is_null());
2242   MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2243 
2244   if (NeedsScopeInfo()) {
2245     scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2246     // The ScopeInfo chain should mirror the context chain, so we only link to
2247     // the next outer scope that needs a context.
2248     if (NeedsContext()) next_outer_scope = scope_info_;
2249   }
2250 
2251   // Allocate ScopeInfos for inner scopes.
2252   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2253     if (!scope->is_function_scope() ||
2254         scope->AsDeclarationScope()->ShouldEagerCompile()) {
2255       scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2256     }
2257   }
2258 }
2259 
AllocateDebuggerScopeInfos(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)2260 void Scope::AllocateDebuggerScopeInfos(Isolate* isolate,
2261                                        MaybeHandle<ScopeInfo> outer_scope) {
2262   if (scope_info_.is_null()) {
2263     scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2264   }
2265   MaybeHandle<ScopeInfo> outer = NeedsContext() ? scope_info_ : outer_scope;
2266   for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2267     if (scope->is_function_scope()) continue;
2268     scope->AllocateDebuggerScopeInfos(isolate, outer);
2269   }
2270 }
2271 
CollectVariableData(PreParsedScopeData * data)2272 void Scope::CollectVariableData(PreParsedScopeData* data) {
2273   PreParsedScopeData::ScopeScope scope_scope(data, scope_type(),
2274                                              start_position(), end_position());
2275   for (Variable* local : locals_) {
2276     scope_scope.MaybeAddVariable(local);
2277   }
2278   for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) {
2279     inner->CollectVariableData(data);
2280   }
2281 }
2282 
StackLocalCount() const2283 int Scope::StackLocalCount() const {
2284   Variable* function =
2285       is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2286   return num_stack_slots() -
2287          (function != nullptr && function->IsStackLocal() ? 1 : 0);
2288 }
2289 
2290 
ContextLocalCount() const2291 int Scope::ContextLocalCount() const {
2292   if (num_heap_slots() == 0) return 0;
2293   Variable* function =
2294       is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2295   bool is_function_var_in_context =
2296       function != nullptr && function->IsContextSlot();
2297   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2298          (is_function_var_in_context ? 1 : 0);
2299 }
2300 
2301 }  // namespace internal
2302 }  // namespace v8
2303