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