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