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