Line data Source code
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/base/optional.h"
12 : #include "src/bootstrapper.h"
13 : #include "src/counters.h"
14 : #include "src/message-template.h"
15 : #include "src/objects-inl.h"
16 : #include "src/objects/module-inl.h"
17 : #include "src/objects/scope-info.h"
18 : #include "src/parsing/parse-info.h"
19 : #include "src/parsing/parser.h"
20 : #include "src/parsing/preparse-data.h"
21 : #include "src/zone/zone-list-inl.h"
22 :
23 : namespace v8 {
24 : namespace internal {
25 :
26 : // ----------------------------------------------------------------------------
27 : // Implementation of LocalsMap
28 : //
29 : // Note: We are storing the handle locations as key values in the hash map.
30 : // When inserting a new variable via Declare(), we rely on the fact that
31 : // the handle location remains alive for the duration of that variable
32 : // use. Because a Variable holding a handle with the same location exists
33 : // this is ensured.
34 :
35 0 : VariableMap::VariableMap(Zone* zone)
36 0 : : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
37 :
38 40444898 : Variable* VariableMap::Declare(Zone* zone, Scope* scope,
39 : const AstRawString* name, VariableMode mode,
40 : VariableKind kind,
41 : InitializationFlag initialization_flag,
42 : MaybeAssignedFlag maybe_assigned_flag,
43 : bool* was_added) {
44 : // AstRawStrings are unambiguous, i.e., the same string is always represented
45 : // by the same AstRawString*.
46 : // FIXME(marja): fix the type of Lookup.
47 : Entry* p =
48 80889871 : ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
49 : ZoneAllocationPolicy(zone));
50 40444973 : *was_added = p->value == nullptr;
51 40444973 : if (*was_added) {
52 : // The variable has not been declared yet -> insert it.
53 : DCHECK_EQ(name, p->key);
54 : Variable* variable = new (zone) Variable(
55 : scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
56 39284423 : p->value = variable;
57 : }
58 40444482 : return reinterpret_cast<Variable*>(p->value);
59 : }
60 :
61 0 : void VariableMap::Remove(Variable* var) {
62 : const AstRawString* name = var->raw_name();
63 3919 : ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
64 0 : }
65 :
66 1015926 : void VariableMap::Add(Zone* zone, Variable* var) {
67 : const AstRawString* name = var->raw_name();
68 : Entry* p =
69 1015929 : ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
70 : ZoneAllocationPolicy(zone));
71 : DCHECK_NULL(p->value);
72 : DCHECK_EQ(name, p->key);
73 1015929 : p->value = var;
74 1015929 : }
75 :
76 89431831 : Variable* VariableMap::Lookup(const AstRawString* name) {
77 : Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
78 89431831 : if (p != nullptr) {
79 : DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
80 : DCHECK_NOT_NULL(p->value);
81 39283926 : return reinterpret_cast<Variable*>(p->value);
82 : }
83 : return nullptr;
84 : }
85 :
86 : // ----------------------------------------------------------------------------
87 : // Implementation of Scope
88 :
89 2990137 : Scope::Scope(Zone* zone)
90 : : zone_(zone),
91 : outer_scope_(nullptr),
92 : variables_(zone),
93 5980286 : scope_type_(SCRIPT_SCOPE) {
94 : SetDefaults();
95 2990149 : }
96 :
97 13042033 : Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
98 : : zone_(zone),
99 : outer_scope_(outer_scope),
100 : variables_(zone),
101 26084137 : scope_type_(scope_type) {
102 : DCHECK_NE(SCRIPT_SCOPE, scope_type);
103 : SetDefaults();
104 : set_language_mode(outer_scope->language_mode());
105 13042104 : outer_scope_->AddInnerScope(this);
106 13042104 : }
107 :
108 2990138 : DeclarationScope::DeclarationScope(Zone* zone,
109 : AstValueFactory* ast_value_factory)
110 5980287 : : Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
111 : DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
112 2990149 : SetDefaults();
113 : receiver_ = DeclareDynamicGlobal(ast_value_factory->this_string(),
114 2990140 : THIS_VARIABLE, this);
115 2990140 : }
116 :
117 6872475 : DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
118 : ScopeType scope_type,
119 : FunctionKind function_kind)
120 : : Scope(zone, outer_scope, scope_type),
121 : function_kind_(function_kind),
122 13744998 : params_(4, zone) {
123 : DCHECK_NE(scope_type, SCRIPT_SCOPE);
124 6872523 : SetDefaults();
125 6872507 : }
126 :
127 71725 : ModuleScope::ModuleScope(DeclarationScope* script_scope,
128 : AstValueFactory* avfactory)
129 : : DeclarationScope(avfactory->zone(), script_scope, MODULE_SCOPE, kModule),
130 : module_descriptor_(new (avfactory->zone())
131 143450 : ModuleDescriptor(avfactory->zone())) {
132 : set_language_mode(LanguageMode::kStrict);
133 71725 : DeclareThis(avfactory);
134 71725 : }
135 :
136 0 : ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
137 : AstValueFactory* avfactory)
138 : : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info),
139 3263 : module_descriptor_(nullptr) {
140 : set_language_mode(LanguageMode::kStrict);
141 0 : }
142 :
143 316072 : ClassScope::ClassScope(Zone* zone, Scope* outer_scope)
144 316072 : : Scope(zone, outer_scope, CLASS_SCOPE) {
145 : set_language_mode(LanguageMode::kStrict);
146 316072 : }
147 :
148 0 : ClassScope::ClassScope(Zone* zone, Handle<ScopeInfo> scope_info)
149 153480 : : Scope(zone, CLASS_SCOPE, scope_info) {
150 : set_language_mode(LanguageMode::kStrict);
151 0 : }
152 :
153 1103626 : Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
154 : : zone_(zone),
155 : outer_scope_(nullptr),
156 : variables_(zone),
157 : scope_info_(scope_info),
158 2207258 : scope_type_(scope_type) {
159 : DCHECK(!scope_info.is_null());
160 : SetDefaults();
161 : #ifdef DEBUG
162 : already_resolved_ = true;
163 : #endif
164 1103632 : if (scope_info->CallsSloppyEval()) scope_calls_eval_ = true;
165 2207264 : set_language_mode(scope_info->language_mode());
166 1103632 : num_heap_slots_ = scope_info->ContextLength();
167 : DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
168 : // We don't really need to use the preparsed scope data; this is just to
169 : // shorten the recursion in SetMustUsePreparseData.
170 1103633 : must_use_preparsed_scope_data_ = true;
171 1103633 : }
172 :
173 905022 : DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
174 : Handle<ScopeInfo> scope_info)
175 : : Scope(zone, scope_type, scope_info),
176 1810053 : function_kind_(scope_info->function_kind()),
177 3620100 : params_(0, zone) {
178 : DCHECK_NE(scope_type, SCRIPT_SCOPE);
179 905026 : SetDefaults();
180 905026 : }
181 :
182 5042 : Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
183 : MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
184 : : zone_(zone),
185 : outer_scope_(nullptr),
186 : variables_(zone),
187 : scope_info_(scope_info),
188 10084 : scope_type_(CATCH_SCOPE) {
189 : SetDefaults();
190 : #ifdef DEBUG
191 : already_resolved_ = true;
192 : #endif
193 : // Cache the catch variable, even though it's also available via the
194 : // scope_info, as the parser expects that a catch scope always has the catch
195 : // variable as first and only variable.
196 : bool was_added;
197 : Variable* variable =
198 : Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
199 : kCreatedInitialized, maybe_assigned, &was_added);
200 : DCHECK(was_added);
201 : AllocateHeapSlot(variable);
202 5042 : }
203 :
204 10767671 : void DeclarationScope::SetDefaults() {
205 10767671 : is_declaration_scope_ = true;
206 10767671 : has_simple_parameters_ = true;
207 10767671 : is_asm_module_ = false;
208 10767671 : force_eager_compilation_ = false;
209 10767671 : has_arguments_parameter_ = false;
210 10767671 : scope_uses_super_property_ = false;
211 10767671 : has_checked_syntax_ = false;
212 10767671 : has_this_reference_ = false;
213 : has_this_declaration_ =
214 17296992 : (is_function_scope() && !is_arrow_scope()) || is_module_scope();
215 10767671 : has_rest_ = false;
216 10767671 : receiver_ = nullptr;
217 10767671 : new_target_ = nullptr;
218 10767671 : function_ = nullptr;
219 10767671 : arguments_ = nullptr;
220 10767671 : rare_data_ = nullptr;
221 10767671 : should_eager_compile_ = false;
222 10767671 : was_lazily_parsed_ = false;
223 10767671 : is_skipped_function_ = false;
224 10767671 : preparse_data_builder_ = nullptr;
225 : #ifdef DEBUG
226 : DeclarationScope* outer_declaration_scope =
227 : outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
228 : is_being_lazily_parsed_ =
229 : outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
230 : : false;
231 : #endif
232 10767671 : }
233 :
234 0 : void Scope::SetDefaults() {
235 : #ifdef DEBUG
236 : scope_name_ = nullptr;
237 : already_resolved_ = false;
238 : needs_migration_ = false;
239 : #endif
240 17140927 : inner_scope_ = nullptr;
241 17140927 : sibling_ = nullptr;
242 : unresolved_list_.Clear();
243 :
244 17140927 : start_position_ = kNoSourcePosition;
245 17140927 : end_position_ = kNoSourcePosition;
246 :
247 17140927 : num_stack_slots_ = 0;
248 17140927 : num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
249 :
250 : set_language_mode(LanguageMode::kSloppy);
251 :
252 17140927 : scope_calls_eval_ = false;
253 17140927 : scope_nonlinear_ = false;
254 17140927 : is_hidden_ = false;
255 17140927 : is_debug_evaluate_scope_ = false;
256 :
257 17140927 : inner_scope_calls_eval_ = false;
258 17140927 : force_context_allocation_ = false;
259 17140927 : force_context_allocation_for_parameters_ = false;
260 :
261 17140927 : is_declaration_scope_ = false;
262 :
263 17140927 : must_use_preparsed_scope_data_ = false;
264 0 : }
265 :
266 432267 : bool Scope::HasSimpleParameters() {
267 : DeclarationScope* scope = GetClosureScope();
268 586639 : return !scope->is_function_scope() || scope->has_simple_parameters();
269 : }
270 :
271 726111 : void DeclarationScope::set_should_eager_compile() {
272 2544162 : should_eager_compile_ = !was_lazily_parsed_;
273 726111 : }
274 :
275 5889 : void DeclarationScope::set_is_asm_module() { is_asm_module_ = true; }
276 :
277 1806500 : bool Scope::IsAsmModule() const {
278 7549083 : return is_function_scope() && AsDeclarationScope()->is_asm_module();
279 : }
280 :
281 6375 : bool Scope::ContainsAsmModule() const {
282 6375 : if (IsAsmModule()) return true;
283 :
284 : // Check inner scopes recursively
285 2553 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
286 : // Don't check inner functions which won't be eagerly compiled.
287 5015 : if (!scope->is_function_scope() ||
288 : scope->AsDeclarationScope()->ShouldEagerCompile()) {
289 2129 : if (scope->ContainsAsmModule()) return true;
290 : }
291 : }
292 :
293 : return false;
294 : }
295 :
296 1021725 : Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
297 : ScopeInfo scope_info,
298 : DeclarationScope* script_scope,
299 : AstValueFactory* ast_value_factory,
300 : DeserializationMode deserialization_mode) {
301 : // Reconstruct the outer scope chain from a closure's context chain.
302 : Scope* current_scope = nullptr;
303 : Scope* innermost_scope = nullptr;
304 : Scope* outer_scope = nullptr;
305 2130398 : while (!scope_info.is_null()) {
306 1442507 : if (scope_info->scope_type() == WITH_SCOPE) {
307 14853 : if (scope_info->IsDebugEvaluateScope()) {
308 : outer_scope = new (zone)
309 25514 : DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
310 : outer_scope->set_is_debug_evaluate_scope();
311 : } else {
312 : // For scope analysis, debug-evaluate is equivalent to a with scope.
313 : outer_scope =
314 4192 : new (zone) Scope(zone, WITH_SCOPE, handle(scope_info, isolate));
315 : }
316 :
317 1427655 : } else if (scope_info->scope_type() == SCRIPT_SCOPE) {
318 : // If we reach a script scope, it's the outermost scope. Install the
319 : // scope info of this script context onto the existing script scope to
320 : // avoid nesting script scopes.
321 333835 : if (deserialization_mode == DeserializationMode::kIncludingVariables) {
322 : script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
323 : }
324 : DCHECK(!scope_info->HasOuterScopeInfo());
325 : break;
326 1093822 : } else if (scope_info->scope_type() == FUNCTION_SCOPE) {
327 : outer_scope = new (zone)
328 1706884 : DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
329 853442 : if (scope_info->IsAsmModule()) {
330 : outer_scope->AsDeclarationScope()->set_is_asm_module();
331 : }
332 240378 : } else if (scope_info->scope_type() == EVAL_SCOPE) {
333 : outer_scope = new (zone)
334 52840 : DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
335 213957 : } else if (scope_info->scope_type() == CLASS_SCOPE) {
336 : outer_scope = new (zone) ClassScope(zone, handle(scope_info, isolate));
337 60476 : } else if (scope_info->scope_type() == BLOCK_SCOPE) {
338 52171 : if (scope_info->is_declaration_scope()) {
339 : outer_scope = new (zone)
340 18283 : DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
341 : } else {
342 : outer_scope =
343 86056 : new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
344 : }
345 8305 : } else if (scope_info->scope_type() == MODULE_SCOPE) {
346 : outer_scope = new (zone)
347 : ModuleScope(isolate, handle(scope_info, isolate), ast_value_factory);
348 : } else {
349 : DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
350 : DCHECK_EQ(scope_info->ContextLocalCount(), 1);
351 : DCHECK_EQ(scope_info->ContextLocalMode(0), VariableMode::kVar);
352 : DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
353 5042 : String name = scope_info->ContextLocalName(0);
354 : MaybeAssignedFlag maybe_assigned =
355 5042 : scope_info->ContextLocalMaybeAssignedFlag(0);
356 : outer_scope = new (zone)
357 : Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
358 15126 : maybe_assigned, handle(scope_info, isolate));
359 : }
360 1108673 : if (deserialization_mode == DeserializationMode::kScopesOnly) {
361 0 : outer_scope->scope_info_ = Handle<ScopeInfo>::null();
362 : }
363 1108673 : if (current_scope != nullptr) {
364 : outer_scope->AddInnerScope(current_scope);
365 : }
366 : current_scope = outer_scope;
367 1108673 : if (innermost_scope == nullptr) innermost_scope = current_scope;
368 1108673 : scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
369 1108672 : : ScopeInfo();
370 : }
371 :
372 2043453 : if (deserialization_mode == DeserializationMode::kIncludingVariables &&
373 : script_scope->scope_info_.is_null()) {
374 : Handle<ScriptContextTable> table(
375 2063679 : isolate->native_context()->script_context_table(), isolate);
376 687893 : Handle<Context> first = ScriptContextTable::GetContext(isolate, table, 0);
377 1375786 : Handle<ScopeInfo> scope_info(first->scope_info(), isolate);
378 : script_scope->SetScriptScopeInfo(scope_info);
379 : }
380 :
381 1021726 : if (innermost_scope == nullptr) return script_scope;
382 867898 : script_scope->AddInnerScope(current_scope);
383 867898 : return innermost_scope;
384 : }
385 :
386 154834575 : DeclarationScope* Scope::AsDeclarationScope() {
387 : DCHECK(is_declaration_scope());
388 154834575 : return static_cast<DeclarationScope*>(this);
389 : }
390 :
391 0 : const DeclarationScope* Scope::AsDeclarationScope() const {
392 : DCHECK(is_declaration_scope());
393 0 : return static_cast<const DeclarationScope*>(this);
394 : }
395 :
396 55331 : ModuleScope* Scope::AsModuleScope() {
397 : DCHECK(is_module_scope());
398 55331 : return static_cast<ModuleScope*>(this);
399 : }
400 :
401 0 : const ModuleScope* Scope::AsModuleScope() const {
402 : DCHECK(is_module_scope());
403 0 : return static_cast<const ModuleScope*>(this);
404 : }
405 :
406 0 : ClassScope* Scope::AsClassScope() {
407 : DCHECK(is_class_scope());
408 0 : return static_cast<ClassScope*>(this);
409 : }
410 :
411 0 : const ClassScope* Scope::AsClassScope() const {
412 : DCHECK(is_class_scope());
413 0 : return static_cast<const ClassScope*>(this);
414 : }
415 :
416 11637 : void DeclarationScope::DeclareSloppyBlockFunction(
417 : SloppyBlockFunctionStatement* sloppy_block_function) {
418 : sloppy_block_functions_.Add(sloppy_block_function);
419 11637 : }
420 :
421 5154785 : void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
422 : DCHECK(is_sloppy(language_mode()));
423 : DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
424 : (is_block_scope() && outer_scope()->is_function_scope()));
425 : DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
426 : DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
427 :
428 5154785 : if (sloppy_block_functions_.is_empty()) return;
429 :
430 : // In case of complex parameters the current scope is the body scope and the
431 : // parameters are stored in the outer scope.
432 10275 : Scope* parameter_scope = HasSimpleParameters() ? this : outer_scope_;
433 : DCHECK(parameter_scope->is_function_scope() || is_eval_scope() ||
434 : is_script_scope());
435 :
436 : DeclarationScope* decl_scope = this;
437 11637 : while (decl_scope->is_eval_scope()) {
438 : decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
439 : }
440 : Scope* outer_scope = decl_scope->outer_scope();
441 :
442 : // For each variable which is used as a function declaration in a sloppy
443 : // block,
444 21833 : for (SloppyBlockFunctionStatement* sloppy_block_function :
445 11558 : sloppy_block_functions_) {
446 : const AstRawString* name = sloppy_block_function->name();
447 :
448 : // If the variable wouldn't conflict with a lexical declaration
449 : // or parameter,
450 :
451 : // Check if there's a conflict with a parameter.
452 : Variable* maybe_parameter = parameter_scope->LookupLocal(name);
453 14343 : if (maybe_parameter != nullptr && maybe_parameter->is_parameter()) {
454 : continue;
455 : }
456 :
457 : // Check if there's a conflict with a lexical declaration
458 : Scope* query_scope = sloppy_block_function->scope()->outer_scope();
459 : Variable* var = nullptr;
460 : bool should_hoist = true;
461 :
462 : // It is not sufficient to just do a Lookup on query_scope: for
463 : // example, that does not prevent hoisting of the function in
464 : // `{ let e; try {} catch (e) { function e(){} } }`
465 : do {
466 16261 : var = query_scope->LookupInScopeOrScopeInfo(name);
467 19528 : if (var != nullptr && IsLexicalVariableMode(var->mode())) {
468 : should_hoist = false;
469 : break;
470 : }
471 : query_scope = query_scope->outer_scope();
472 14855 : } while (query_scope != outer_scope);
473 :
474 11365 : if (!should_hoist) continue;
475 :
476 9959 : if (factory) {
477 : DCHECK(!is_being_lazily_parsed_);
478 : int pos = sloppy_block_function->position();
479 7527 : bool ok = true;
480 : bool was_added;
481 : auto declaration = factory->NewVariableDeclaration(pos);
482 : // Based on the preceding checks, it doesn't matter what we pass as
483 : // sloppy_mode_block_scope_function_redefinition.
484 : Variable* var = DeclareVariable(
485 : declaration, name, pos, VariableMode::kVar, NORMAL_VARIABLE,
486 : Variable::DefaultInitializationFlag(VariableMode::kVar), &was_added,
487 7527 : nullptr, &ok);
488 : DCHECK(ok);
489 : VariableProxy* source =
490 : factory->NewVariableProxy(sloppy_block_function->var());
491 : VariableProxy* target = factory->NewVariableProxy(var);
492 7527 : Assignment* assignment = factory->NewAssignment(
493 7527 : sloppy_block_function->init(), target, source, pos);
494 : assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
495 : Statement* statement = factory->NewExpressionStatement(assignment, pos);
496 : sloppy_block_function->set_statement(statement);
497 : } else {
498 : DCHECK(is_being_lazily_parsed_);
499 : bool was_added;
500 2432 : Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
501 2432 : if (sloppy_block_function->init() == Token::ASSIGN)
502 : var->set_maybe_assigned();
503 : }
504 : }
505 : }
506 :
507 1818051 : bool DeclarationScope::Analyze(ParseInfo* info) {
508 : RuntimeCallTimerScope runtimeTimer(
509 : info->runtime_call_stats(),
510 : info->on_background_thread()
511 : ? RuntimeCallCounterId::kCompileBackgroundScopeAnalysis
512 1818051 : : RuntimeCallCounterId::kCompileScopeAnalysis);
513 : DCHECK_NOT_NULL(info->literal());
514 : DeclarationScope* scope = info->literal()->scope();
515 :
516 : base::Optional<AllowHandleDereference> allow_deref;
517 : if (!info->maybe_outer_scope_info().is_null()) {
518 : // Allow dereferences to the scope info if there is one.
519 : allow_deref.emplace();
520 : }
521 :
522 2679107 : if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
523 734968 : AstNodeFactory factory(info->ast_value_factory(), info->zone());
524 734968 : scope->HoistSloppyBlockFunctions(&factory);
525 : }
526 :
527 : // We are compiling one of four cases:
528 : // 1) top-level code,
529 : // 2) a function/eval/module on the top-level
530 : // 3) a function/eval in a scope that was already resolved.
531 : DCHECK(scope->is_script_scope() || scope->outer_scope()->is_script_scope() ||
532 : scope->outer_scope()->already_resolved_);
533 :
534 : // The outer scope is never lazy.
535 : scope->set_should_eager_compile();
536 :
537 1818051 : if (scope->must_use_preparsed_scope_data_) {
538 : DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
539 : allow_deref.emplace();
540 36544 : info->consumed_preparse_data()->RestoreScopeAllocationData(scope);
541 : }
542 :
543 1818051 : if (!scope->AllocateVariables(info)) return false;
544 :
545 : #ifdef DEBUG
546 : if (FLAG_print_scopes) {
547 : PrintF("Global scope:\n");
548 : scope->Print();
549 : }
550 : scope->CheckScopePositions();
551 : scope->CheckZones();
552 : #endif
553 :
554 1818047 : return true;
555 : }
556 :
557 5303476 : void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
558 : DCHECK(has_this_declaration());
559 :
560 5303476 : bool derived_constructor = IsDerivedConstructor(function_kind_);
561 :
562 : receiver_ = new (zone())
563 : Variable(this, ast_value_factory->this_string(),
564 : derived_constructor ? VariableMode::kConst : VariableMode::kVar,
565 : THIS_VARIABLE,
566 : derived_constructor ? kNeedsInitialization : kCreatedInitialized,
567 10606962 : kNotAssigned);
568 5303481 : }
569 :
570 4156434 : void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
571 : DCHECK(is_function_scope());
572 : DCHECK(!is_arrow_scope());
573 :
574 : // Declare 'arguments' variable which exists in all non arrow functions. Note
575 : // that it might never be accessed, in which case it won't be allocated during
576 : // variable allocation.
577 : bool was_added;
578 : arguments_ =
579 4156434 : Declare(zone(), ast_value_factory->arguments_string(), VariableMode::kVar,
580 4156478 : NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
581 4159239 : if (!was_added && IsLexicalVariableMode(arguments_->mode())) {
582 : // Check if there's lexically declared variable named arguments to avoid
583 : // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
584 622 : arguments_ = nullptr;
585 : }
586 4156478 : }
587 :
588 4590066 : void DeclarationScope::DeclareDefaultFunctionVariables(
589 : AstValueFactory* ast_value_factory) {
590 : DCHECK(is_function_scope());
591 : DCHECK(!is_arrow_scope());
592 :
593 4590066 : DeclareThis(ast_value_factory);
594 : bool was_added;
595 4590070 : new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
596 : VariableMode::kConst, NORMAL_VARIABLE,
597 4590062 : kCreatedInitialized, kNotAssigned, &was_added);
598 : DCHECK(was_added);
599 :
600 16836117 : if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
601 : IsAccessorFunction(function_kind_)) {
602 : EnsureRareData()->this_function = Declare(
603 : zone(), ast_value_factory->this_function_string(), VariableMode::kConst,
604 945490 : NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
605 : DCHECK(was_added);
606 : }
607 4590067 : }
608 :
609 1016824 : Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
610 : Scope* cache) {
611 : DCHECK(is_function_scope());
612 : DCHECK_NULL(function_);
613 1016824 : if (cache == nullptr) cache = this;
614 : DCHECK_NULL(cache->variables_.Lookup(name));
615 : VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
616 1016824 : : NORMAL_VARIABLE;
617 : function_ = new (zone())
618 2033652 : Variable(this, name, VariableMode::kConst, kind, kCreatedInitialized);
619 1016826 : if (calls_sloppy_eval()) {
620 899 : cache->NonLocal(name, VariableMode::kDynamic);
621 : } else {
622 1015927 : cache->variables_.Add(zone(), function_);
623 : }
624 1016829 : return function_;
625 : }
626 :
627 142482 : Variable* DeclarationScope::DeclareGeneratorObjectVar(
628 : const AstRawString* name) {
629 : DCHECK(is_function_scope() || is_module_scope());
630 : DCHECK_NULL(generator_object_var());
631 :
632 : Variable* result = EnsureRareData()->generator_object =
633 142482 : NewTemporary(name, kNotAssigned);
634 : result->set_is_used();
635 142482 : return result;
636 : }
637 :
638 5290237 : Scope* Scope::FinalizeBlockScope() {
639 : DCHECK(is_block_scope());
640 : #ifdef DEBUG
641 : DCHECK_NE(sibling_, this);
642 : #endif
643 :
644 15083419 : if (variables_.occupancy() > 0 ||
645 70414 : (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
646 : return this;
647 : }
648 :
649 : DCHECK(!is_class_scope());
650 :
651 : // Remove this scope from outer scope.
652 : outer_scope()->RemoveInnerScope(this);
653 :
654 : // Reparent inner scopes.
655 4500498 : if (inner_scope_ != nullptr) {
656 : Scope* scope = inner_scope_;
657 561935 : scope->outer_scope_ = outer_scope();
658 652033 : while (scope->sibling_ != nullptr) {
659 : scope = scope->sibling_;
660 45049 : scope->outer_scope_ = outer_scope();
661 : }
662 561935 : scope->sibling_ = outer_scope()->inner_scope_;
663 561935 : outer_scope()->inner_scope_ = inner_scope_;
664 561935 : inner_scope_ = nullptr;
665 : }
666 :
667 : // Move unresolved variables
668 4500498 : if (!unresolved_list_.is_empty()) {
669 : outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
670 : unresolved_list_.Clear();
671 : }
672 :
673 4500498 : if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
674 :
675 : // No need to propagate scope_calls_eval_, since if it was relevant to
676 : // this scope we would have had to bail out at the top.
677 : DCHECK(!scope_calls_eval_ || !is_declaration_scope() ||
678 : !is_sloppy(language_mode()));
679 :
680 : // This block does not need a context.
681 4500498 : num_heap_slots_ = 0;
682 :
683 : // Mark scope as removed by making it its own sibling.
684 : #ifdef DEBUG
685 : sibling_ = this;
686 : #endif
687 :
688 4500498 : return nullptr;
689 : }
690 :
691 0 : void DeclarationScope::AddLocal(Variable* var) {
692 : DCHECK(!already_resolved_);
693 : // Temporaries are only placed in ClosureScopes.
694 : DCHECK_EQ(GetClosureScope(), this);
695 : locals_.Add(var);
696 0 : }
697 :
698 133518 : void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
699 : DCHECK(!IsCleared());
700 : DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
701 : DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
702 : DCHECK_EQ(new_parent, new_parent->GetClosureScope());
703 : DCHECK_NULL(new_parent->inner_scope_);
704 : DCHECK(new_parent->unresolved_list_.is_empty());
705 133518 : Scope* inner_scope = new_parent->sibling_;
706 133518 : if (inner_scope != top_inner_scope_) {
707 3644 : for (; inner_scope->sibling() != top_inner_scope_;
708 : inner_scope = inner_scope->sibling()) {
709 0 : inner_scope->outer_scope_ = new_parent;
710 0 : if (inner_scope->inner_scope_calls_eval_) {
711 0 : new_parent->inner_scope_calls_eval_ = true;
712 : }
713 : DCHECK_NE(inner_scope, new_parent);
714 : }
715 3644 : inner_scope->outer_scope_ = new_parent;
716 3644 : if (inner_scope->inner_scope_calls_eval_) {
717 128 : new_parent->inner_scope_calls_eval_ = true;
718 : }
719 3644 : new_parent->inner_scope_ = new_parent->sibling_;
720 3644 : inner_scope->sibling_ = nullptr;
721 : // Reset the sibling rather than the inner_scope_ since we
722 : // want to keep new_parent there.
723 3644 : new_parent->sibling_ = top_inner_scope_;
724 : }
725 :
726 : Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
727 : new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
728 : top_unresolved_);
729 :
730 : // Move temporaries allocated for complex parameter initializers.
731 : DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
732 133518 : for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
733 12 : Variable* local = *it;
734 : DCHECK_EQ(VariableMode::kTemporary, local->mode());
735 : DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
736 : DCHECK_NE(local->scope(), new_parent);
737 : local->set_scope(new_parent);
738 : }
739 : new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
740 : outer_closure->locals_.Rewind(top_local_);
741 :
742 : // Move eval calls since Snapshot's creation into new_parent.
743 133518 : if (outer_scope_and_calls_eval_->scope_calls_eval_) {
744 419 : new_parent->scope_calls_eval_ = true;
745 419 : new_parent->inner_scope_calls_eval_ = true;
746 : }
747 :
748 : // We are in the arrow function case. The calls eval we may have recorded
749 : // is intended for the inner scope and we should simply restore the
750 : // original "calls eval" flag of the outer scope.
751 : RestoreEvalFlag();
752 : Clear();
753 133518 : }
754 :
755 91 : void Scope::ReplaceOuterScope(Scope* outer) {
756 : DCHECK_NOT_NULL(outer);
757 : DCHECK_NOT_NULL(outer_scope_);
758 : DCHECK(!already_resolved_);
759 91 : outer_scope_->RemoveInnerScope(this);
760 : outer->AddInnerScope(this);
761 : outer_scope_ = outer;
762 91 : }
763 :
764 2512449 : Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
765 : DCHECK(!scope_info_.is_null());
766 : DCHECK_NULL(cache->variables_.Lookup(name));
767 : DisallowHeapAllocation no_gc;
768 :
769 2512449 : String name_handle = *name->string();
770 : // The Scope is backed up by ScopeInfo. This means it cannot operate in a
771 : // heap-independent mode, and all strings must be internalized immediately. So
772 : // it's ok to get the Handle<String> here.
773 : bool found = false;
774 :
775 : VariableLocation location;
776 : int index;
777 : VariableMode mode;
778 : InitializationFlag init_flag;
779 : MaybeAssignedFlag maybe_assigned_flag;
780 :
781 : {
782 : location = VariableLocation::CONTEXT;
783 : index = ScopeInfo::ContextSlotIndex(*scope_info_, name_handle, &mode,
784 2512449 : &init_flag, &maybe_assigned_flag);
785 2512454 : found = index >= 0;
786 : }
787 :
788 2512454 : if (!found && is_module_scope()) {
789 : location = VariableLocation::MODULE;
790 3982 : index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
791 1991 : &maybe_assigned_flag);
792 1991 : found = index != 0;
793 : }
794 :
795 2512454 : if (!found) {
796 2047346 : index = scope_info_->FunctionContextSlotIndex(name_handle);
797 2047348 : if (index < 0) return nullptr; // Nowhere found.
798 1041 : Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
799 : DCHECK_EQ(VariableMode::kConst, var->mode());
800 : var->AllocateTo(VariableLocation::CONTEXT, index);
801 1041 : return cache->variables_.Lookup(name);
802 : }
803 :
804 : if (!is_module_scope()) {
805 : DCHECK_NE(index, scope_info_->ReceiverContextSlotIndex());
806 : }
807 :
808 : bool was_added;
809 : Variable* var =
810 465108 : cache->variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
811 465108 : init_flag, maybe_assigned_flag, &was_added);
812 : DCHECK(was_added);
813 : var->AllocateTo(location, index);
814 465105 : return var;
815 : }
816 :
817 2939097 : Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
818 : VariableMode mode,
819 : bool is_optional, bool is_rest,
820 : AstValueFactory* ast_value_factory,
821 : int position) {
822 : DCHECK(!already_resolved_);
823 : DCHECK(is_function_scope() || is_module_scope());
824 : DCHECK(!has_rest_);
825 : DCHECK(!is_optional || !is_rest);
826 : DCHECK(!is_being_lazily_parsed_);
827 : DCHECK(!was_lazily_parsed_);
828 : Variable* var;
829 2939097 : if (mode == VariableMode::kTemporary) {
830 219630 : var = NewTemporary(name);
831 : } else {
832 2829283 : var = LookupLocal(name);
833 : DCHECK_EQ(mode, VariableMode::kVar);
834 : DCHECK(var->is_parameter());
835 : }
836 2939098 : has_rest_ = is_rest;
837 2939098 : var->set_initializer_position(position);
838 2939098 : params_.Add(var, zone());
839 2939098 : if (!is_rest) ++num_parameters_;
840 2939098 : if (name == ast_value_factory->arguments_string()) {
841 1454 : has_arguments_parameter_ = true;
842 : }
843 : // Params are automatically marked as used to make sure that the debugger and
844 : // function.arguments sees them.
845 : // TODO(verwaest): Reevaluate whether we always need to do this, since
846 : // strict-mode function.arguments does not make the arguments available.
847 2939098 : var->set_is_used();
848 2939098 : return var;
849 : }
850 :
851 4012751 : void DeclarationScope::RecordParameter(bool is_rest) {
852 : DCHECK(!already_resolved_);
853 : DCHECK(is_function_scope() || is_module_scope());
854 : DCHECK(is_being_lazily_parsed_);
855 : DCHECK(!has_rest_);
856 4012751 : has_rest_ = is_rest;
857 4012751 : if (!is_rest) ++num_parameters_;
858 4012751 : }
859 :
860 24187814 : Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
861 : VariableKind kind, bool* was_added,
862 : InitializationFlag init_flag) {
863 : DCHECK(!already_resolved_);
864 : // This function handles VariableMode::kVar, VariableMode::kLet, and
865 : // VariableMode::kConst modes. VariableMode::kDynamic variables are
866 : // introduced during variable allocation, and VariableMode::kTemporary
867 : // variables are allocated via NewTemporary().
868 : DCHECK(IsDeclaredVariableMode(mode));
869 : DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
870 : mode == VariableMode::kVar || mode == VariableMode::kLet ||
871 : mode == VariableMode::kConst);
872 : DCHECK(!GetDeclarationScope()->was_lazily_parsed());
873 : Variable* var =
874 : Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);
875 :
876 : // Pessimistically assume that top-level variables will be assigned and used.
877 : //
878 : // Top-level variables in a script can be accessed by other scripts or even
879 : // become global properties. While this does not apply to top-level variables
880 : // in a module (assuming they are not exported), we must still mark these as
881 : // assigned because they might be accessed by a lazily parsed top-level
882 : // function, which, for efficiency, we preparse without variable tracking.
883 24187588 : if (is_script_scope() || is_module_scope()) {
884 4163958 : if (mode != VariableMode::kConst) var->set_maybe_assigned();
885 : var->set_is_used();
886 : }
887 :
888 24187588 : return var;
889 : }
890 :
891 15840078 : Variable* Scope::DeclareVariable(
892 : Declaration* declaration, const AstRawString* name, int pos,
893 : VariableMode mode, VariableKind kind, InitializationFlag init,
894 : bool* was_added, bool* sloppy_mode_block_scope_function_redefinition,
895 : bool* ok) {
896 : DCHECK(IsDeclaredVariableMode(mode));
897 : DCHECK(!already_resolved_);
898 : DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
899 : DCHECK(!GetDeclarationScope()->was_lazily_parsed());
900 :
901 29902234 : if (mode == VariableMode::kVar && !is_declaration_scope()) {
902 806674 : return GetDeclarationScope()->DeclareVariable(
903 : declaration, name, pos, mode, kind, init, was_added,
904 403337 : sloppy_mode_block_scope_function_redefinition, ok);
905 : }
906 : DCHECK(!is_catch_scope());
907 : DCHECK(!is_with_scope());
908 : DCHECK(is_declaration_scope() ||
909 : (IsLexicalVariableMode(mode) && is_block_scope()));
910 :
911 : DCHECK_NOT_NULL(name);
912 :
913 : Variable* var = LookupLocal(name);
914 : // Declare the variable in the declaration scope.
915 15436773 : *was_added = var == nullptr;
916 15436773 : if (V8_LIKELY(*was_added)) {
917 14633570 : if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
918 : mode == VariableMode::kVar)) {
919 : // In a var binding in a sloppy direct eval, pollute the enclosing scope
920 : // with this new binding by doing the following:
921 : // The proxy is bound to a lookup variable to force a dynamic declaration
922 : // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
923 : DCHECK_EQ(NORMAL_VARIABLE, kind);
924 307486 : var = NonLocal(name, VariableMode::kDynamic);
925 : // Mark the var as used in case anyone outside the eval wants to use it.
926 : var->set_is_used();
927 : } else {
928 : // Declare the name.
929 13514524 : var = DeclareLocal(name, mode, kind, was_added, init);
930 : DCHECK(*was_added);
931 : }
932 : } else {
933 : var->set_maybe_assigned();
934 3179648 : if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
935 : IsLexicalVariableMode(var->mode()))) {
936 : // The name was declared in this scope before; check for conflicting
937 : // re-declarations. We have a conflict if either of the declarations is
938 : // not a var (in script scope, we also have to ignore legacy const for
939 : // compatibility). There is similar code in runtime.cc in the Declare
940 : // functions. The function CheckConflictingVarDeclarations checks for
941 : // var and let bindings from different scopes whereas this is a check
942 : // for conflicting declarations within the same scope. This check also
943 : // covers the special case
944 : //
945 : // function () { let x; { var x; } }
946 : //
947 : // because the var declaration is hoisted to the function scope where
948 : // 'x' is already bound.
949 : //
950 : // In harmony we treat re-declarations as early errors. See ES5 16 for a
951 : // definition of early errors.
952 : //
953 : // Allow duplicate function decls for web compat, see bug 4693.
954 64038 : *ok = var->is_sloppy_block_function() &&
955 64038 : kind == SLOPPY_BLOCK_FUNCTION_VARIABLE;
956 64038 : *sloppy_mode_block_scope_function_redefinition = *ok;
957 : }
958 : }
959 : DCHECK_NOT_NULL(var);
960 :
961 : // We add a declaration node for every declaration. The compiler
962 : // will only generate code if necessary. In particular, declarations
963 : // for inner local variables that do not represent functions won't
964 : // result in any generated code.
965 : //
966 : // This will lead to multiple declaration nodes for the
967 : // same variable if it is declared several times. This is not a
968 : // semantic issue, but it may be a performance issue since it may
969 : // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
970 : decls_.Add(declaration);
971 : declaration->set_var(var);
972 15436587 : return var;
973 : }
974 :
975 11132730 : Variable* Scope::DeclareVariableName(const AstRawString* name,
976 : VariableMode mode, bool* was_added,
977 : VariableKind kind) {
978 : DCHECK(IsDeclaredVariableMode(mode));
979 : DCHECK(!already_resolved_);
980 : DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
981 :
982 20830277 : if (mode == VariableMode::kVar && !is_declaration_scope()) {
983 1138066 : return GetDeclarationScope()->DeclareVariableName(name, mode, was_added,
984 569033 : kind);
985 : }
986 : DCHECK(!is_with_scope());
987 : DCHECK(!is_eval_scope());
988 : DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode));
989 : DCHECK(scope_info_.is_null());
990 :
991 : // Declare the variable in the declaration scope.
992 10563697 : Variable* var = DeclareLocal(name, mode, kind, was_added);
993 10563751 : if (!*was_added) {
994 1737275 : if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) {
995 321 : if (!var->is_sloppy_block_function() ||
996 : kind != SLOPPY_BLOCK_FUNCTION_VARIABLE) {
997 : // Duplicate functions are allowed in the sloppy mode, but if this is
998 : // not a function declaration, it's an error. This is an error PreParser
999 : // hasn't previously detected.
1000 : return nullptr;
1001 : }
1002 : // Sloppy block function redefinition.
1003 : }
1004 : var->set_maybe_assigned();
1005 : }
1006 : var->set_is_used();
1007 10563536 : return var;
1008 : }
1009 :
1010 380626 : Variable* Scope::DeclareCatchVariableName(const AstRawString* name) {
1011 : DCHECK(!already_resolved_);
1012 : DCHECK(is_catch_scope());
1013 : DCHECK(scope_info_.is_null());
1014 :
1015 : bool was_added;
1016 : Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE,
1017 : kCreatedInitialized, kNotAssigned, &was_added);
1018 : DCHECK(was_added);
1019 380635 : return result;
1020 : }
1021 :
1022 50872566 : void Scope::AddUnresolved(VariableProxy* proxy) {
1023 : DCHECK(!already_resolved_);
1024 : DCHECK(!proxy->is_resolved());
1025 : unresolved_list_.Add(proxy);
1026 50872566 : }
1027 :
1028 0 : Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1029 : VariableKind kind,
1030 : Scope* cache) {
1031 : DCHECK(is_script_scope());
1032 : bool was_added;
1033 4968524 : return cache->variables_.Declare(
1034 : zone(), this, name, VariableMode::kDynamicGlobal, kind,
1035 4968524 : kCreatedInitialized, kNotAssigned, &was_added);
1036 : // TODO(neis): Mark variable as maybe-assigned?
1037 : }
1038 :
1039 1289 : bool Scope::RemoveUnresolved(VariableProxy* var) {
1040 1289 : return unresolved_list_.Remove(var);
1041 : }
1042 :
1043 15738 : void Scope::DeleteUnresolved(VariableProxy* var) {
1044 : DCHECK(unresolved_list_.Contains(var));
1045 : var->mark_removed_from_unresolved();
1046 15738 : }
1047 :
1048 1241193 : Variable* Scope::NewTemporary(const AstRawString* name) {
1049 1351008 : return NewTemporary(name, kMaybeAssigned);
1050 : }
1051 :
1052 1493494 : Variable* Scope::NewTemporary(const AstRawString* name,
1053 : MaybeAssignedFlag maybe_assigned) {
1054 : DeclarationScope* scope = GetClosureScope();
1055 : Variable* var = new (zone()) Variable(scope, name, VariableMode::kTemporary,
1056 : NORMAL_VARIABLE, kCreatedInitialized);
1057 : scope->AddLocal(var);
1058 1493496 : if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1059 1493496 : return var;
1060 : }
1061 :
1062 6633977 : Declaration* DeclarationScope::CheckConflictingVarDeclarations() {
1063 6633977 : if (has_checked_syntax_) return nullptr;
1064 19491038 : for (Declaration* decl : decls_) {
1065 : // Lexical vs lexical conflicts within the same scope have already been
1066 : // captured in Parser::Declare. The only conflicts we still need to check
1067 : // are lexical vs nested var.
1068 25205658 : if (decl->IsVariableDeclaration() &&
1069 12159117 : decl->AsVariableDeclaration()->AsNested() != nullptr) {
1070 939871 : Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
1071 : DCHECK(decl->var()->mode() == VariableMode::kVar ||
1072 : decl->var()->mode() == VariableMode::kDynamic);
1073 : // Iterate through all scopes until the declaration scope.
1074 : do {
1075 : // There is a conflict if there exists a non-VAR binding.
1076 1362105 : if (current->is_catch_scope()) {
1077 : current = current->outer_scope();
1078 2852 : continue;
1079 : }
1080 : Variable* other_var = current->LookupLocal(decl->var()->raw_name());
1081 1359253 : if (other_var != nullptr) {
1082 : DCHECK(IsLexicalVariableMode(other_var->mode()));
1083 : return decl;
1084 : }
1085 : current = current->outer_scope();
1086 1348976 : } while (current != this);
1087 : }
1088 : }
1089 :
1090 6444497 : if (V8_LIKELY(!is_eval_scope())) return nullptr;
1091 862833 : if (!is_sloppy(language_mode())) return nullptr;
1092 :
1093 : // Var declarations in sloppy eval are hoisted to the first non-eval
1094 : // declaration scope. Check for conflicts between the eval scope that
1095 : // declaration scope.
1096 735656 : Scope* end = this;
1097 735662 : do {
1098 735662 : end = end->outer_scope_->GetDeclarationScope();
1099 : } while (end->is_eval_scope());
1100 735656 : end = end->outer_scope_;
1101 :
1102 1036499 : for (Declaration* decl : decls_) {
1103 300996 : if (IsLexicalVariableMode(decl->var()->mode())) continue;
1104 289517 : Scope* current = outer_scope_;
1105 : // Iterate through all scopes until and including the declaration scope.
1106 : do {
1107 : // There is a conflict if there exists a non-VAR binding up to the
1108 : // declaration scope in which this sloppy-eval runs.
1109 : Variable* other_var =
1110 289726 : current->LookupInScopeOrScopeInfo(decl->var()->raw_name());
1111 290289 : if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
1112 : DCHECK(!current->is_catch_scope());
1113 : return decl;
1114 : }
1115 : current = current->outer_scope();
1116 289573 : } while (current != end);
1117 : }
1118 : return nullptr;
1119 : }
1120 :
1121 85426 : const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope,
1122 : VariableMode mode_limit) {
1123 : const VariableMap& variables = scope->variables_;
1124 885298 : for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr;
1125 : p = variables.Next(p)) {
1126 400263 : const AstRawString* name = static_cast<const AstRawString*>(p->key);
1127 : Variable* var = LookupLocal(name);
1128 401754 : if (var != nullptr && var->mode() <= mode_limit) return name;
1129 : }
1130 : return nullptr;
1131 : }
1132 :
1133 785310 : void DeclarationScope::DeserializeReceiver(AstValueFactory* ast_value_factory) {
1134 785310 : if (is_script_scope()) {
1135 : DCHECK_NOT_NULL(receiver_);
1136 : return;
1137 : }
1138 : DCHECK(has_this_declaration());
1139 641690 : DeclareThis(ast_value_factory);
1140 641690 : if (is_debug_evaluate_scope()) {
1141 12241 : receiver_->AllocateTo(VariableLocation::LOOKUP, -1);
1142 : } else {
1143 1258898 : receiver_->AllocateTo(VariableLocation::CONTEXT,
1144 : scope_info_->ReceiverContextSlotIndex());
1145 : }
1146 : }
1147 :
1148 1818049 : bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1149 : // Module variables must be allocated before variable resolution
1150 : // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1151 1818049 : if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1152 :
1153 1818053 : ClassScope* closest_class_scope = GetClassScope();
1154 1971468 : if (closest_class_scope != nullptr &&
1155 153418 : !closest_class_scope->ResolvePrivateNames(info)) {
1156 : DCHECK(info->pending_error_handler()->has_pending_error());
1157 : return false;
1158 : }
1159 :
1160 1818035 : if (!ResolveVariablesRecursively(info)) {
1161 : DCHECK(info->pending_error_handler()->has_pending_error());
1162 : return false;
1163 : }
1164 :
1165 : // // Don't allocate variables of preparsed scopes.
1166 1818039 : if (!was_lazily_parsed()) AllocateVariablesRecursively();
1167 :
1168 : return true;
1169 : }
1170 :
1171 4313 : bool Scope::HasThisReference() const {
1172 7870 : if (is_declaration_scope() && AsDeclarationScope()->has_this_reference()) {
1173 : return true;
1174 : }
1175 :
1176 5062 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1177 4426 : if (!scope->is_declaration_scope() ||
1178 : !scope->AsDeclarationScope()->has_this_declaration()) {
1179 2368 : if (scope->HasThisReference()) return true;
1180 : }
1181 : }
1182 :
1183 : return false;
1184 : }
1185 :
1186 4190654 : bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1187 : const Scope* outer) const {
1188 : // If none of the outer scopes need to decide whether to context allocate
1189 : // specific variables, we can preparse inner functions without unresolved
1190 : // variables. Otherwise we need to find unresolved variables to force context
1191 : // allocation of the matching declarations. We can stop at the outer scope for
1192 : // the parse, since context allocation of those variables is already
1193 : // guaranteed to be correct.
1194 4190912 : for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1195 : // Eval forces context allocation on all outer scopes, so we don't need to
1196 : // look at those scopes. Sloppy eval makes top-level non-lexical variables
1197 : // dynamic, whereas strict-mode requires context allocation.
1198 3151510 : if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1199 : // Catch scopes force context allocation of all variables.
1200 2130318 : if (s->is_catch_scope()) continue;
1201 : // With scopes do not introduce variables that need allocation.
1202 2130318 : if (s->is_with_scope()) continue;
1203 : DCHECK(s->is_module_scope() || s->is_block_scope() ||
1204 : s->is_function_scope());
1205 : return false;
1206 : }
1207 : return true;
1208 : }
1209 :
1210 3636820 : bool DeclarationScope::AllowsLazyCompilation() const {
1211 : // Functions which force eager compilation and class member initializer
1212 : // functions are not lazily compilable.
1213 3636820 : return !force_eager_compilation_ &&
1214 3636820 : !IsClassMembersInitializerFunction(function_kind());
1215 : }
1216 :
1217 2838126 : int Scope::ContextChainLength(Scope* scope) const {
1218 : int n = 0;
1219 4318322 : for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1220 : DCHECK_NOT_NULL(s); // scope must be in the scope chain
1221 740098 : if (s->NeedsContext()) n++;
1222 : }
1223 2838126 : return n;
1224 : }
1225 :
1226 355514 : int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1227 : int result = 0;
1228 : int length = 0;
1229 :
1230 2547452 : for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1231 1095969 : if (!s->NeedsContext()) continue;
1232 796663 : length++;
1233 1578374 : if (s->is_declaration_scope() &&
1234 : s->AsDeclarationScope()->calls_sloppy_eval()) {
1235 : result = length;
1236 : }
1237 : }
1238 :
1239 355514 : return result;
1240 : }
1241 :
1242 2571912 : ClassScope* Scope::GetClassScope() {
1243 : Scope* scope = this;
1244 14890887 : while (scope != nullptr && !scope->is_class_scope()) {
1245 : scope = scope->outer_scope();
1246 : }
1247 4392143 : if (scope != nullptr && scope->is_class_scope()) {
1248 375267 : return scope->AsClassScope();
1249 : }
1250 : return nullptr;
1251 : }
1252 :
1253 17469757 : DeclarationScope* Scope::GetDeclarationScope() {
1254 : Scope* scope = this;
1255 25015335 : while (!scope->is_declaration_scope()) {
1256 : scope = scope->outer_scope();
1257 : }
1258 17469757 : return scope->AsDeclarationScope();
1259 : }
1260 :
1261 0 : const DeclarationScope* Scope::GetClosureScope() const {
1262 : const Scope* scope = this;
1263 0 : while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1264 : scope = scope->outer_scope();
1265 : }
1266 0 : return scope->AsDeclarationScope();
1267 : }
1268 :
1269 9501099 : DeclarationScope* Scope::GetClosureScope() {
1270 : Scope* scope = this;
1271 35127173 : while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1272 : scope = scope->outer_scope();
1273 : }
1274 9501099 : return scope->AsDeclarationScope();
1275 : }
1276 :
1277 0 : bool Scope::NeedsScopeInfo() const {
1278 : DCHECK(!already_resolved_);
1279 : DCHECK(GetClosureScope()->ShouldEagerCompile());
1280 : // The debugger expects all functions to have scope infos.
1281 : // TODO(jochen|yangguo): Remove this requirement.
1282 2421923 : if (is_function_scope()) return true;
1283 0 : return NeedsContext();
1284 : }
1285 :
1286 43944 : bool Scope::ShouldBanArguments() {
1287 43944 : return GetReceiverScope()->should_ban_arguments();
1288 : }
1289 :
1290 8954606 : DeclarationScope* Scope::GetReceiverScope() {
1291 : Scope* scope = this;
1292 18694002 : while (!scope->is_declaration_scope() ||
1293 9047940 : (!scope->is_script_scope() &&
1294 : !scope->AsDeclarationScope()->has_this_declaration())) {
1295 : scope = scope->outer_scope();
1296 : }
1297 8954606 : return scope->AsDeclarationScope();
1298 : }
1299 :
1300 2626530 : Scope* Scope::GetOuterScopeWithContext() {
1301 2626530 : Scope* scope = outer_scope_;
1302 3556478 : while (scope && !scope->NeedsContext()) {
1303 : scope = scope->outer_scope();
1304 : }
1305 2626530 : return scope;
1306 : }
1307 :
1308 : namespace {
1309 : bool WasLazilyParsed(Scope* scope) {
1310 21826727 : return scope->is_declaration_scope() &&
1311 : scope->AsDeclarationScope()->was_lazily_parsed();
1312 : }
1313 :
1314 : } // namespace
1315 :
1316 : template <typename FunctionType>
1317 : void Scope::ForEach(FunctionType callback) {
1318 : Scope* scope = this;
1319 : while (true) {
1320 12068658 : Iteration iteration = callback(scope);
1321 : // Try to descend into inner scopes first.
1322 12068680 : if ((iteration == Iteration::kDescend) && scope->inner_scope_ != nullptr) {
1323 : scope = scope->inner_scope_;
1324 : } else {
1325 : // Find the next outer scope with a sibling.
1326 12068688 : while (scope->sibling_ == nullptr) {
1327 5199776 : if (scope == this) return;
1328 2996652 : scope = scope->outer_scope_;
1329 : }
1330 6868912 : if (scope == this) return;
1331 : scope = scope->sibling_;
1332 : }
1333 : }
1334 : }
1335 :
1336 12578 : void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1337 : Isolate* isolate, ParseInfo* info,
1338 : Handle<StringSet>* non_locals) {
1339 90654 : this->ForEach([max_outer_scope, isolate, info, non_locals](Scope* scope) {
1340 : // Module variables must be allocated before variable resolution
1341 : // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1342 17057 : if (scope->is_module_scope()) {
1343 228 : scope->AsModuleScope()->AllocateModuleVariables();
1344 : }
1345 :
1346 : // Lazy parsed declaration scopes are already partially analyzed. If there
1347 : // are unresolved references remaining, they just need to be resolved in
1348 : // outer scopes.
1349 17057 : Scope* lookup = WasLazilyParsed(scope) ? scope->outer_scope() : scope;
1350 :
1351 74421 : for (VariableProxy* proxy : scope->unresolved_list_) {
1352 : DCHECK(!proxy->is_resolved());
1353 : Variable* var =
1354 57364 : Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1355 57364 : if (var == nullptr) {
1356 16233 : *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1357 : } else {
1358 : // In this case we need to leave scopes in a way that they can be
1359 : // allocated. If we resolved variables from lazy parsed scopes, we need
1360 : // to context allocate the var.
1361 : scope->ResolveTo(info, proxy, var);
1362 41131 : if (!var->is_dynamic() && lookup != scope)
1363 : var->ForceContextAllocation();
1364 : }
1365 : }
1366 :
1367 : // Clear unresolved_list_ as it's in an inconsistent state.
1368 : scope->unresolved_list_.Clear();
1369 17057 : return Iteration::kDescend;
1370 : });
1371 12578 : }
1372 :
1373 1908312 : void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1374 : AstNodeFactory* ast_node_factory,
1375 : UnresolvedList* new_unresolved_list) {
1376 : this->ForEach([max_outer_scope, ast_node_factory,
1377 46201691 : new_unresolved_list](Scope* scope) {
1378 : DCHECK_IMPLIES(scope->is_declaration_scope(),
1379 : !scope->AsDeclarationScope()->was_lazily_parsed());
1380 :
1381 22889769 : for (VariableProxy* proxy = scope->unresolved_list_.first();
1382 26065043 : proxy != nullptr; proxy = proxy->next_unresolved()) {
1383 : DCHECK(!proxy->is_resolved());
1384 : Variable* var =
1385 22889527 : Lookup<kParsedScope>(proxy, scope, max_outer_scope->outer_scope());
1386 22889786 : if (var == nullptr) {
1387 : // Don't copy unresolved references to the script scope, unless it's a
1388 : // reference to a private name or method. In that case keep it so we
1389 : // can fail later.
1390 6827117 : if (!max_outer_scope->outer_scope()->is_script_scope()) {
1391 : VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1392 : new_unresolved_list->Add(copy);
1393 : }
1394 : } else {
1395 : var->set_is_used();
1396 16062669 : if (proxy->is_assigned()) var->set_maybe_assigned();
1397 : }
1398 : }
1399 :
1400 : // Clear unresolved_list_ as it's in an inconsistent state.
1401 : scope->unresolved_list_.Clear();
1402 3175516 : return Iteration::kDescend;
1403 : });
1404 1908319 : }
1405 :
1406 12578 : Handle<StringSet> DeclarationScope::CollectNonLocals(
1407 : Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
1408 12578 : Scope::CollectNonLocals(this, isolate, info, &non_locals);
1409 12578 : return non_locals;
1410 : }
1411 :
1412 2614481 : void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1413 : bool aborted) {
1414 : DCHECK(is_function_scope());
1415 :
1416 : // Reset all non-trivial members.
1417 : params_.Clear();
1418 : decls_.Clear();
1419 : locals_.Clear();
1420 2614481 : inner_scope_ = nullptr;
1421 : unresolved_list_.Clear();
1422 : sloppy_block_functions_.Clear();
1423 2614481 : rare_data_ = nullptr;
1424 2614481 : has_rest_ = false;
1425 :
1426 : DCHECK_NE(zone_, ast_value_factory->zone());
1427 2614481 : zone_->ReleaseMemory();
1428 :
1429 2614568 : if (aborted) {
1430 : // Prepare scope for use in the outer zone.
1431 49034 : zone_ = ast_value_factory->zone();
1432 49034 : variables_.Reset(ZoneAllocationPolicy(zone_));
1433 98068 : if (!IsArrowFunction(function_kind_)) {
1434 43288 : has_simple_parameters_ = true;
1435 43288 : DeclareDefaultFunctionVariables(ast_value_factory);
1436 : }
1437 : } else {
1438 : // Make sure this scope isn't used for allocation anymore.
1439 2565534 : zone_ = nullptr;
1440 : variables_.Invalidate();
1441 : }
1442 :
1443 : #ifdef DEBUG
1444 : needs_migration_ = false;
1445 : is_being_lazily_parsed_ = false;
1446 : #endif
1447 :
1448 2614568 : was_lazily_parsed_ = !aborted;
1449 2614568 : }
1450 :
1451 280195 : bool Scope::IsSkippableFunctionScope() {
1452 : // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
1453 : // those Scopes which have their own PreparseDataBuilder object. This
1454 : // logic ensures that the scope allocation data is consistent with the
1455 : // skippable function data (both agree on where the lazy function boundaries
1456 : // are).
1457 3455699 : if (!is_function_scope()) return false;
1458 : DeclarationScope* declaration_scope = AsDeclarationScope();
1459 2784289 : return !declaration_scope->is_arrow_scope() &&
1460 : declaration_scope->preparse_data_builder() != nullptr;
1461 : }
1462 :
1463 1908313 : void Scope::SavePreparseData(Parser* parser) {
1464 5226464 : this->ForEach([parser](Scope* scope) {
1465 3175504 : if (scope->IsSkippableFunctionScope()) {
1466 : scope->AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
1467 : }
1468 3175498 : return Iteration::kDescend;
1469 : });
1470 1908317 : }
1471 :
1472 0 : void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
1473 2050960 : if (preparse_data_builder_ == nullptr) return;
1474 2050959 : preparse_data_builder_->SaveScopeAllocationData(this, parser);
1475 : }
1476 :
1477 2504644 : void DeclarationScope::AnalyzePartially(Parser* parser,
1478 : AstNodeFactory* ast_node_factory) {
1479 : DCHECK(!force_eager_compilation_);
1480 : UnresolvedList new_unresolved_list;
1481 9992722 : if (!IsArrowFunction(function_kind_) &&
1482 3110357 : (!outer_scope_->is_script_scope() ||
1483 1263094 : (preparse_data_builder_ != nullptr &&
1484 631557 : preparse_data_builder_->HasInnerFunctions()))) {
1485 : // Try to resolve unresolved variables for this Scope and migrate those
1486 : // which cannot be resolved inside. It doesn't make sense to try to resolve
1487 : // them in the outer Scopes here, because they are incomplete.
1488 1908320 : Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list);
1489 :
1490 : // Migrate function_ to the right Zone.
1491 1908333 : if (function_ != nullptr) {
1492 861771 : function_ = ast_node_factory->CopyVariable(function_);
1493 : }
1494 :
1495 1908324 : SavePreparseData(parser);
1496 : }
1497 :
1498 : #ifdef DEBUG
1499 : if (FLAG_print_scopes) {
1500 : PrintF("Inner function scope:\n");
1501 : Print();
1502 : }
1503 : #endif
1504 :
1505 2504631 : ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1506 :
1507 : unresolved_list_ = std::move(new_unresolved_list);
1508 2504744 : }
1509 :
1510 : #ifdef DEBUG
1511 : namespace {
1512 :
1513 : const char* Header(ScopeType scope_type, FunctionKind function_kind,
1514 : bool is_declaration_scope) {
1515 : switch (scope_type) {
1516 : case EVAL_SCOPE: return "eval";
1517 : // TODO(adamk): Should we print concise method scopes specially?
1518 : case FUNCTION_SCOPE:
1519 : if (IsGeneratorFunction(function_kind)) return "function*";
1520 : if (IsAsyncFunction(function_kind)) return "async function";
1521 : if (IsArrowFunction(function_kind)) return "arrow";
1522 : return "function";
1523 : case MODULE_SCOPE: return "module";
1524 : case SCRIPT_SCOPE: return "global";
1525 : case CATCH_SCOPE: return "catch";
1526 : case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1527 : case CLASS_SCOPE:
1528 : return "class";
1529 : case WITH_SCOPE: return "with";
1530 : }
1531 : UNREACHABLE();
1532 : }
1533 :
1534 : void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1535 :
1536 : void PrintName(const AstRawString* name) {
1537 : PrintF("%.*s", name->length(), name->raw_data());
1538 : }
1539 :
1540 : void PrintLocation(Variable* var) {
1541 : switch (var->location()) {
1542 : case VariableLocation::UNALLOCATED:
1543 : break;
1544 : case VariableLocation::PARAMETER:
1545 : PrintF("parameter[%d]", var->index());
1546 : break;
1547 : case VariableLocation::LOCAL:
1548 : PrintF("local[%d]", var->index());
1549 : break;
1550 : case VariableLocation::CONTEXT:
1551 : PrintF("context[%d]", var->index());
1552 : break;
1553 : case VariableLocation::LOOKUP:
1554 : PrintF("lookup");
1555 : break;
1556 : case VariableLocation::MODULE:
1557 : PrintF("module");
1558 : break;
1559 : }
1560 : }
1561 :
1562 : void PrintVar(int indent, Variable* var) {
1563 : Indent(indent, VariableMode2String(var->mode()));
1564 : PrintF(" ");
1565 : if (var->raw_name()->IsEmpty())
1566 : PrintF(".%p", reinterpret_cast<void*>(var));
1567 : else
1568 : PrintName(var->raw_name());
1569 : PrintF("; // (%p) ", reinterpret_cast<void*>(var));
1570 : PrintLocation(var);
1571 : bool comma = !var->IsUnallocated();
1572 : if (var->has_forced_context_allocation()) {
1573 : if (comma) PrintF(", ");
1574 : PrintF("forced context allocation");
1575 : comma = true;
1576 : }
1577 : if (var->maybe_assigned() == kNotAssigned) {
1578 : if (comma) PrintF(", ");
1579 : PrintF("never assigned");
1580 : comma = true;
1581 : }
1582 : if (var->initialization_flag() == kNeedsInitialization &&
1583 : !var->binding_needs_init()) {
1584 : if (comma) PrintF(", ");
1585 : PrintF("hole initialization elided");
1586 : }
1587 : PrintF("\n");
1588 : }
1589 :
1590 : void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1591 : Variable* function_var) {
1592 : bool printed_label = false;
1593 : for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1594 : Variable* var = reinterpret_cast<Variable*>(p->value);
1595 : if (var == function_var) continue;
1596 : bool local = !IsDynamicVariableMode(var->mode());
1597 : if ((locals ? local : !local) &&
1598 : (var->is_used() || !var->IsUnallocated())) {
1599 : if (!printed_label) {
1600 : Indent(indent, label);
1601 : printed_label = true;
1602 : }
1603 : PrintVar(indent, var);
1604 : }
1605 : }
1606 : }
1607 :
1608 : } // anonymous namespace
1609 :
1610 : void DeclarationScope::PrintParameters() {
1611 : PrintF(" (");
1612 : for (int i = 0; i < params_.length(); i++) {
1613 : if (i > 0) PrintF(", ");
1614 : const AstRawString* name = params_[i]->raw_name();
1615 : if (name->IsEmpty()) {
1616 : PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1617 : } else {
1618 : PrintName(name);
1619 : }
1620 : }
1621 : PrintF(")");
1622 : }
1623 :
1624 : void Scope::Print(int n) {
1625 : int n0 = (n > 0 ? n : 0);
1626 : int n1 = n0 + 2; // indentation
1627 :
1628 : // Print header.
1629 : FunctionKind function_kind = is_function_scope()
1630 : ? AsDeclarationScope()->function_kind()
1631 : : kNormalFunction;
1632 : Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1633 : if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1634 : PrintF(" ");
1635 : PrintName(scope_name_);
1636 : }
1637 :
1638 : // Print parameters, if any.
1639 : Variable* function = nullptr;
1640 : if (is_function_scope()) {
1641 : AsDeclarationScope()->PrintParameters();
1642 : function = AsDeclarationScope()->function_var();
1643 : }
1644 :
1645 : PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
1646 : start_position(), end_position());
1647 : if (is_hidden()) {
1648 : Indent(n1, "// is hidden\n");
1649 : }
1650 :
1651 : // Function name, if any (named function literals, only).
1652 : if (function != nullptr) {
1653 : Indent(n1, "// (local) function name: ");
1654 : PrintName(function->raw_name());
1655 : PrintF("\n");
1656 : }
1657 :
1658 : // Scope info.
1659 : if (is_strict(language_mode())) {
1660 : Indent(n1, "// strict mode scope\n");
1661 : }
1662 : if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1663 : if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
1664 : Indent(n1, "// scope calls sloppy 'eval'\n");
1665 : }
1666 : if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) {
1667 : Indent(n1, "// scope needs home object\n");
1668 : }
1669 : if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1670 : if (is_declaration_scope()) {
1671 : DeclarationScope* scope = AsDeclarationScope();
1672 : if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1673 : if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1674 : }
1675 : if (num_stack_slots_ > 0) {
1676 : Indent(n1, "// ");
1677 : PrintF("%d stack slots\n", num_stack_slots_);
1678 : }
1679 : if (num_heap_slots_ > 0) {
1680 : Indent(n1, "// ");
1681 : PrintF("%d heap slots\n", num_heap_slots_);
1682 : }
1683 :
1684 : // Print locals.
1685 : if (function != nullptr) {
1686 : Indent(n1, "// function var:\n");
1687 : PrintVar(n1, function);
1688 : }
1689 :
1690 : // Print temporaries.
1691 : {
1692 : bool printed_header = false;
1693 : for (Variable* local : locals_) {
1694 : if (local->mode() != VariableMode::kTemporary) continue;
1695 : if (!printed_header) {
1696 : printed_header = true;
1697 : Indent(n1, "// temporary vars:\n");
1698 : }
1699 : PrintVar(n1, local);
1700 : }
1701 : }
1702 :
1703 : if (variables_.occupancy() > 0) {
1704 : PrintMap(n1, "// local vars:\n", &variables_, true, function);
1705 : PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1706 : }
1707 :
1708 : if (is_class_scope()) {
1709 : ClassScope* class_scope = AsClassScope();
1710 : if (class_scope->rare_data_ != nullptr) {
1711 : PrintMap(n1, "// private name vars:\n",
1712 : &(class_scope->rare_data_->private_name_map), true, function);
1713 : }
1714 : }
1715 :
1716 : // Print inner scopes (disable by providing negative n).
1717 : if (n >= 0) {
1718 : for (Scope* scope = inner_scope_; scope != nullptr;
1719 : scope = scope->sibling_) {
1720 : PrintF("\n");
1721 : scope->Print(n1);
1722 : }
1723 : }
1724 :
1725 : Indent(n0, "}\n");
1726 : }
1727 :
1728 : void Scope::CheckScopePositions() {
1729 : this->ForEach([](Scope* scope) {
1730 : // Visible leaf scopes must have real positions.
1731 : if (!scope->is_hidden() && scope->inner_scope_ == nullptr) {
1732 : DCHECK_NE(kNoSourcePosition, scope->start_position());
1733 : DCHECK_NE(kNoSourcePosition, scope->end_position());
1734 : }
1735 : return Iteration::kDescend;
1736 : });
1737 : }
1738 :
1739 : void Scope::CheckZones() {
1740 : DCHECK(!needs_migration_);
1741 : this->ForEach([](Scope* scope) {
1742 : if (WasLazilyParsed(scope)) {
1743 : DCHECK_NULL(scope->zone());
1744 : DCHECK_NULL(scope->inner_scope_);
1745 : return Iteration::kContinue;
1746 : }
1747 : return Iteration::kDescend;
1748 : });
1749 : }
1750 : #endif // DEBUG
1751 :
1752 727014 : Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1753 : // Declare a new non-local.
1754 : DCHECK(IsDynamicVariableMode(mode));
1755 : bool was_added;
1756 : Variable* var =
1757 727014 : variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
1758 727014 : kCreatedInitialized, kNotAssigned, &was_added);
1759 : // Allocate it by giving it a dynamic lookup.
1760 : var->AllocateTo(VariableLocation::LOOKUP, -1);
1761 727015 : return var;
1762 : }
1763 :
1764 : // static
1765 : template <Scope::ScopeLookupMode mode>
1766 43980159 : Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
1767 : Scope* outer_scope_end, Scope* entry_point,
1768 : bool force_context_allocation) {
1769 : if (mode == kDeserializedScope) {
1770 2098008 : Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
1771 2098012 : if (var != nullptr) return var;
1772 : }
1773 :
1774 502721 : while (true) {
1775 : DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
1776 : // Short-cut: whenever we find a debug-evaluate scope, just look everything
1777 : // up dynamically. Debug-evaluate doesn't properly create scope info for the
1778 : // lookups it does. It may not have a valid 'this' declaration, and anything
1779 : // accessed through debug-evaluate might invalidly resolve to
1780 : // stack-allocated variables.
1781 : // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
1782 : // the scopes in which it's evaluating.
1783 2240000 : if (mode == kDeserializedScope &&
1784 2240000 : V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
1785 10725 : return entry_point->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1786 : }
1787 :
1788 : // Try to find the variable in this scope.
1789 : Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
1790 : : scope->LookupInScopeInfo(
1791 2229275 : proxy->raw_name(), entry_point);
1792 :
1793 : // We found a variable and we are done. (Even if there is an 'eval' in this
1794 : // scope which introduces the same variable again, the resulting variable
1795 : // remains the same.)
1796 61460894 : if (var != nullptr) {
1797 39384729 : if (mode == kParsedScope && force_context_allocation &&
1798 : !var->is_dynamic()) {
1799 : var->ForceContextAllocation();
1800 : }
1801 : return var;
1802 : }
1803 :
1804 28874309 : if (scope->outer_scope_ == outer_scope_end) break;
1805 :
1806 : DCHECK(!scope->is_script_scope());
1807 20051778 : if (V8_UNLIKELY(scope->is_with_scope())) {
1808 46198 : return LookupWith(proxy, scope, outer_scope_end, entry_point,
1809 46198 : force_context_allocation);
1810 : }
1811 35671104 : if (V8_UNLIKELY(scope->is_declaration_scope() &&
1812 : scope->AsDeclarationScope()->calls_sloppy_eval())) {
1813 387262 : return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
1814 387262 : force_context_allocation);
1815 : }
1816 :
1817 19618318 : force_context_allocation |= scope->is_function_scope();
1818 : scope = scope->outer_scope_;
1819 : // TODO(verwaest): Separate through AnalyzePartially.
1820 19115597 : if (mode == kParsedScope && !scope->scope_info_.is_null()) {
1821 1777833 : return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
1822 : }
1823 : }
1824 :
1825 : // We may just be trying to find all free variables. In that case, don't
1826 : // declare them in the outer scope.
1827 : // TODO(marja): Separate Lookup for preparsed scopes better.
1828 7853477 : if (mode == kParsedScope && !scope->is_script_scope()) {
1829 : return nullptr;
1830 : }
1831 :
1832 : // No binding has been found. Declare a variable on the global object.
1833 : return scope->AsDeclarationScope()->DeclareDynamicGlobal(
1834 : proxy->raw_name(), NORMAL_VARIABLE,
1835 1978377 : mode == kDeserializedScope ? entry_point : scope);
1836 : }
1837 :
1838 : template Variable* Scope::Lookup<Scope::kParsedScope>(
1839 : VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1840 : Scope* entry_point, bool force_context_allocation);
1841 : template Variable* Scope::Lookup<Scope::kDeserializedScope>(
1842 : VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1843 : Scope* entry_point, bool force_context_allocation);
1844 :
1845 46198 : Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
1846 : Scope* outer_scope_end, Scope* entry_point,
1847 : bool force_context_allocation) {
1848 : DCHECK(scope->is_with_scope());
1849 :
1850 : Variable* var =
1851 46198 : scope->outer_scope_->scope_info_.is_null()
1852 44577 : ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1853 : nullptr, force_context_allocation)
1854 : : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1855 90775 : outer_scope_end, entry_point);
1856 :
1857 46198 : if (var == nullptr) return var;
1858 :
1859 : // The current scope is a with scope, so the variable binding can not be
1860 : // statically resolved. However, note that it was necessary to do a lookup
1861 : // in the outer scope anyway, because if a binding exists in an outer
1862 : // scope, the associated variable has to be marked as potentially being
1863 : // accessed from inside of an inner with scope (the property may not be in
1864 : // the 'with' object).
1865 41039 : if (!var->is_dynamic() && var->IsUnallocated()) {
1866 : DCHECK(!scope->already_resolved_);
1867 : var->set_is_used();
1868 : var->ForceContextAllocation();
1869 11849 : if (proxy->is_assigned()) var->set_maybe_assigned();
1870 : }
1871 28950 : if (entry_point != nullptr) entry_point->variables_.Remove(var);
1872 28950 : Scope* target = entry_point == nullptr ? scope : entry_point;
1873 28950 : return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1874 : }
1875 :
1876 387262 : Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
1877 : Scope* outer_scope_end, Scope* entry_point,
1878 : bool force_context_allocation) {
1879 : DCHECK(scope->is_declaration_scope() &&
1880 : scope->AsDeclarationScope()->calls_sloppy_eval());
1881 :
1882 : // If we're compiling eval, it's possible that the outer scope is the first
1883 : // ScopeInfo-backed scope.
1884 387262 : Scope* entry = entry_point == nullptr ? scope->outer_scope_ : entry_point;
1885 : Variable* var =
1886 387262 : scope->outer_scope_->scope_info_.is_null()
1887 68706 : ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1888 : nullptr, force_context_allocation)
1889 : : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1890 455968 : outer_scope_end, entry);
1891 387262 : if (var == nullptr) return var;
1892 :
1893 : // A variable binding may have been found in an outer scope, but the current
1894 : // scope makes a sloppy 'eval' call, so the found variable may not be the
1895 : // correct one (the 'eval' may introduce a binding with the same name). In
1896 : // that case, change the lookup result to reflect this situation. Only
1897 : // scopes that can host var bindings (declaration scopes) need be considered
1898 : // here (this excludes block and catch scopes), and variable lookups at
1899 : // script scope are always dynamic.
1900 380908 : if (var->IsGlobalObjectProperty()) {
1901 374459 : Scope* target = entry_point == nullptr ? scope : entry_point;
1902 374459 : return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
1903 : }
1904 :
1905 6449 : if (var->is_dynamic()) return var;
1906 :
1907 : Variable* invalidated = var;
1908 4495 : if (entry_point != nullptr) entry_point->variables_.Remove(invalidated);
1909 :
1910 4495 : Scope* target = entry_point == nullptr ? scope : entry_point;
1911 4495 : var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
1912 : var->set_local_if_not_shadowed(invalidated);
1913 :
1914 4495 : return var;
1915 : }
1916 :
1917 18832175 : void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1918 : DCHECK(info->script_scope()->is_script_scope());
1919 : DCHECK(!proxy->is_resolved());
1920 18832175 : Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
1921 : DCHECK_NOT_NULL(var);
1922 : ResolveTo(info, proxy, var);
1923 18832170 : }
1924 :
1925 : namespace {
1926 :
1927 : void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
1928 : proxy->set_needs_hole_check();
1929 : var->ForceHoleInitialization();
1930 : }
1931 :
1932 18873575 : void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1933 18877439 : if (var->mode() == VariableMode::kDynamicLocal) {
1934 : // Dynamically introduced variables never need a hole check (since they're
1935 : // VariableMode::kVar bindings, either from var or function declarations),
1936 : // but the variable they shadow might need a hole check, which we want to do
1937 : // if we decide that no shadowing variable was dynamically introoduced.
1938 : DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
1939 3864 : return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
1940 : }
1941 :
1942 18873575 : if (var->initialization_flag() == kCreatedInitialized) return;
1943 :
1944 : // It's impossible to eliminate module import hole checks here, because it's
1945 : // unknown at compilation time whether the binding referred to in the
1946 : // exporting module itself requires hole checks.
1947 1568795 : if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
1948 : return SetNeedsHoleCheck(var, proxy);
1949 : }
1950 :
1951 : // Check if the binding really needs an initialization check. The check
1952 : // can be skipped in the following situation: we have a VariableMode::kLet or
1953 : // VariableMode::kConst binding, both the Variable and the VariableProxy have
1954 : // the same declaration scope (i.e. they are both in global code, in the same
1955 : // function or in the same eval code), the VariableProxy is in the source
1956 : // physically located after the initializer of the variable, and that the
1957 : // initializer cannot be skipped due to a nonlinear scope.
1958 : //
1959 : // The condition on the closure scopes is a conservative check for
1960 : // nested functions that access a binding and are called before the
1961 : // binding is initialized:
1962 : // function() { f(); let x = 1; function f() { x = 2; } }
1963 : //
1964 : // The check cannot be skipped on non-linear scopes, namely switch
1965 : // scopes, to ensure tests are done in cases like the following:
1966 : // switch (1) { case 0: let x = 2; case 1: f(x); }
1967 : // The scope of the variable needs to be checked, in case the use is
1968 : // in a sub-block which may be linear.
1969 1567484 : if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
1970 : return SetNeedsHoleCheck(var, proxy);
1971 : }
1972 :
1973 : // We should always have valid source positions.
1974 : DCHECK_NE(var->initializer_position(), kNoSourcePosition);
1975 : DCHECK_NE(proxy->position(), kNoSourcePosition);
1976 :
1977 966750 : if (var->scope()->is_nonlinear() ||
1978 : var->initializer_position() >= proxy->position()) {
1979 : return SetNeedsHoleCheck(var, proxy);
1980 : }
1981 : }
1982 :
1983 : } // anonymous namespace
1984 :
1985 0 : void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1986 : DCHECK_NOT_NULL(var);
1987 18873714 : UpdateNeedsHoleCheck(var, proxy, this);
1988 18873456 : proxy->BindTo(var);
1989 0 : }
1990 :
1991 6651595 : void Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
1992 : Scope* end) {
1993 : // Resolve the variable in all parsed scopes to force context allocation.
1994 15462053 : for (; scope != end; scope = scope->outer_scope_) {
1995 : Variable* var = scope->LookupLocal(proxy->raw_name());
1996 6668181 : if (var != nullptr) {
1997 : var->set_is_used();
1998 2264543 : if (!var->is_dynamic()) {
1999 : var->ForceContextAllocation();
2000 2262952 : if (proxy->is_assigned()) var->set_maybe_assigned();
2001 : return;
2002 : }
2003 : }
2004 : }
2005 : }
2006 :
2007 5700617 : bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
2008 : DCHECK(info->script_scope()->is_script_scope());
2009 : // Lazy parsed declaration scopes are already partially analyzed. If there are
2010 : // unresolved references remaining, they just need to be resolved in outer
2011 : // scopes.
2012 5700617 : if (WasLazilyParsed(this)) {
2013 : DCHECK_EQ(variables_.occupancy(), 0);
2014 2474287 : Scope* end = info->scope();
2015 : // Resolve in all parsed scopes except for the script scope.
2016 2474284 : if (!end->is_script_scope()) end = end->outer_scope();
2017 :
2018 9125915 : for (VariableProxy* proxy : unresolved_list_) {
2019 6651627 : ResolvePreparsedVariable(proxy, outer_scope(), end);
2020 : }
2021 : } else {
2022 : // Resolve unresolved variables for this scope.
2023 22058527 : for (VariableProxy* proxy : unresolved_list_) {
2024 18832206 : ResolveVariable(info, proxy);
2025 : }
2026 :
2027 : // Resolve unresolved variables for inner scopes.
2028 7108871 : for (Scope* scope = inner_scope_; scope != nullptr;
2029 : scope = scope->sibling_) {
2030 3882567 : if (!scope->ResolveVariablesRecursively(info)) return false;
2031 : }
2032 : }
2033 : return true;
2034 : }
2035 :
2036 19160657 : bool Scope::MustAllocate(Variable* var) {
2037 : DCHECK(var->location() != VariableLocation::MODULE);
2038 : // Give var a read/write use if there is a chance it might be accessed
2039 : // via an eval() call. This is only possible if the variable has a
2040 : // visible name.
2041 57441502 : if (!var->raw_name()->IsEmpty() &&
2042 35416211 : (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2043 : var->set_is_used();
2044 4192940 : if (inner_scope_calls_eval_) var->set_maybe_assigned();
2045 : }
2046 : DCHECK(!var->has_forced_context_allocation() || var->is_used());
2047 : // Global variables do not need to be allocated.
2048 36517728 : return !var->IsGlobalObjectProperty() && var->is_used();
2049 : }
2050 :
2051 :
2052 11284705 : bool Scope::MustAllocateInContext(Variable* var) {
2053 : // If var is accessed from an inner scope, or if there is a possibility
2054 : // that it might be accessed from the current or an inner scope (through
2055 : // an eval() call or a runtime with lookup), it must be allocated in the
2056 : // context.
2057 : //
2058 : // Temporary variables are always stack-allocated. Catch-bound variables are
2059 : // always context-allocated.
2060 11284705 : if (var->mode() == VariableMode::kTemporary) return false;
2061 10027828 : if (is_catch_scope()) return true;
2062 9926125 : if ((is_script_scope() || is_eval_scope()) &&
2063 : IsLexicalVariableMode(var->mode())) {
2064 : return true;
2065 : }
2066 9250880 : return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2067 : }
2068 :
2069 :
2070 6391044 : void Scope::AllocateStackSlot(Variable* var) {
2071 6779164 : if (is_block_scope()) {
2072 388120 : outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2073 : } else {
2074 6391044 : var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2075 : }
2076 6391044 : }
2077 :
2078 :
2079 : void Scope::AllocateHeapSlot(Variable* var) {
2080 2361607 : var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2081 : }
2082 :
2083 : void DeclarationScope::AllocateParameterLocals() {
2084 : DCHECK(is_function_scope());
2085 :
2086 : bool has_mapped_arguments = false;
2087 1604297 : if (arguments_ != nullptr) {
2088 : DCHECK(!is_arrow_scope());
2089 1085744 : if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2090 : // 'arguments' is used and does not refer to a function
2091 : // parameter of the same name. If the arguments object
2092 : // aliases formal parameters, we conservatively allocate
2093 : // them specially in the loop below.
2094 : has_mapped_arguments =
2095 116785 : GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2096 : } else {
2097 : // 'arguments' is unused. Tell the code generator that it does not need to
2098 : // allocate the arguments object by nulling out arguments_.
2099 968961 : arguments_ = nullptr;
2100 : }
2101 : }
2102 :
2103 : // The same parameter may occur multiple times in the parameters_ list.
2104 : // If it does, and if it is not copied into the context object, it must
2105 : // receive the highest parameter index for that parameter; thus iteration
2106 : // order is relevant!
2107 4097256 : for (int i = num_parameters() - 1; i >= 0; --i) {
2108 2492955 : Variable* var = params_[i];
2109 : DCHECK_NOT_NULL(var);
2110 : DCHECK(!has_rest_ || var != rest_parameter());
2111 : DCHECK_EQ(this, var->scope());
2112 2492955 : if (has_mapped_arguments) {
2113 : var->set_is_used();
2114 : var->set_maybe_assigned();
2115 : var->ForceContextAllocation();
2116 : }
2117 : AllocateParameter(var, i);
2118 : }
2119 : }
2120 :
2121 : void DeclarationScope::AllocateParameter(Variable* var, int index) {
2122 3629489 : if (!MustAllocate(var)) return;
2123 5397479 : if (has_forced_context_allocation_for_parameters() ||
2124 2698739 : MustAllocateInContext(var)) {
2125 : DCHECK(var->IsUnallocated() || var->IsContextSlot());
2126 163826 : if (var->IsUnallocated()) AllocateHeapSlot(var);
2127 : } else {
2128 : DCHECK(var->IsUnallocated() || var->IsParameter());
2129 2534914 : if (var->IsUnallocated()) {
2130 : var->AllocateTo(VariableLocation::PARAMETER, index);
2131 : }
2132 : }
2133 : }
2134 :
2135 : void DeclarationScope::AllocateReceiver() {
2136 2722401 : if (!has_this_declaration()) return;
2137 : DCHECK_NOT_NULL(receiver());
2138 : DCHECK_EQ(receiver()->scope(), this);
2139 : AllocateParameter(receiver(), -1);
2140 : }
2141 :
2142 15547717 : void Scope::AllocateNonParameterLocal(Variable* var) {
2143 : DCHECK_EQ(var->scope(), this);
2144 15547717 : if (var->IsUnallocated() && MustAllocate(var)) {
2145 8583922 : if (MustAllocateInContext(var)) {
2146 : AllocateHeapSlot(var);
2147 : DCHECK_IMPLIES(is_catch_scope(),
2148 : var->index() == Context::THROWN_OBJECT_INDEX);
2149 : } else {
2150 6391045 : AllocateStackSlot(var);
2151 : }
2152 : }
2153 15547728 : }
2154 :
2155 : void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2156 37503341 : for (Variable* local : locals_) {
2157 15525335 : AllocateNonParameterLocal(local);
2158 : }
2159 :
2160 3226341 : if (is_declaration_scope()) {
2161 : AsDeclarationScope()->AllocateLocals();
2162 : }
2163 : }
2164 :
2165 : void DeclarationScope::AllocateLocals() {
2166 : // For now, function_ must be allocated at the very end. If it gets
2167 : // allocated in the context, it must be the last slot in the context,
2168 : // because of the current ScopeInfo implementation (see
2169 : // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2170 2722416 : if (function_ != nullptr && MustAllocate(function_)) {
2171 22393 : AllocateNonParameterLocal(function_);
2172 : } else {
2173 2700022 : function_ = nullptr;
2174 : }
2175 :
2176 : DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2177 : !rest_parameter()->IsUnallocated());
2178 :
2179 2722414 : if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2180 1008155 : new_target_ = nullptr;
2181 : }
2182 :
2183 : NullifyRareVariableIf(RareVariable::kThisFunction,
2184 170253 : [=](Variable* var) { return !MustAllocate(var); });
2185 : }
2186 :
2187 9130 : void ModuleScope::AllocateModuleVariables() {
2188 10336 : for (const auto& it : module()->regular_imports()) {
2189 1206 : Variable* var = LookupLocal(it.first);
2190 1206 : var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2191 : DCHECK(!var->IsExport());
2192 : }
2193 :
2194 27890 : for (const auto& it : module()->regular_exports()) {
2195 18760 : Variable* var = LookupLocal(it.first);
2196 18760 : var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2197 : DCHECK(var->IsExport());
2198 : }
2199 9130 : }
2200 :
2201 1818031 : void Scope::AllocateVariablesRecursively() {
2202 5700572 : this->ForEach([](Scope* scope) -> Iteration {
2203 : DCHECK(!scope->already_resolved_);
2204 5700572 : if (WasLazilyParsed(scope)) return Iteration::kContinue;
2205 : DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope->num_heap_slots_);
2206 :
2207 : // Allocate variables for this scope.
2208 : // Parameters must be allocated first, if any.
2209 3226321 : if (scope->is_declaration_scope()) {
2210 2722397 : if (scope->is_function_scope()) {
2211 : scope->AsDeclarationScope()->AllocateParameterLocals();
2212 : }
2213 : scope->AsDeclarationScope()->AllocateReceiver();
2214 : }
2215 : scope->AllocateNonParameterLocalsAndDeclaredGlobals();
2216 :
2217 : // Force allocation of a context for this scope if necessary. For a 'with'
2218 : // scope and for a function scope that makes an 'eval' call we need a
2219 : // context, even if no local variables were statically allocated in the
2220 : // scope. Likewise for modules and function scopes representing asm.js
2221 : // modules. Also force a context, if the scope is stricter than the outer
2222 : // scope.
2223 : bool must_have_context =
2224 6368509 : scope->is_with_scope() || scope->is_module_scope() ||
2225 3175519 : scope->IsAsmModule() || scope->ForceContextForLanguageMode() ||
2226 1600031 : (scope->is_function_scope() &&
2227 6316483 : scope->AsDeclarationScope()->calls_sloppy_eval()) ||
2228 360482 : (scope->is_block_scope() && scope->is_declaration_scope() &&
2229 : scope->AsDeclarationScope()->calls_sloppy_eval());
2230 :
2231 : // If we didn't allocate any locals in the local context, then we only
2232 : // need the minimal number of slots if we must have a context.
2233 3226342 : if (scope->num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
2234 : !must_have_context) {
2235 2775440 : scope->num_heap_slots_ = 0;
2236 : }
2237 :
2238 : // Allocation done.
2239 : DCHECK(scope->num_heap_slots_ == 0 ||
2240 : scope->num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2241 : return Iteration::kDescend;
2242 : });
2243 1818042 : }
2244 :
2245 2421923 : void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
2246 : MaybeHandle<ScopeInfo> outer_scope) {
2247 : DCHECK(scope_info_.is_null());
2248 2421923 : MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2249 :
2250 2421923 : if (NeedsScopeInfo()) {
2251 1270023 : scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2252 : // The ScopeInfo chain should mirror the context chain, so we only link to
2253 : // the next outer scope that needs a context.
2254 1270020 : if (NeedsContext()) next_outer_scope = scope_info_;
2255 : }
2256 :
2257 : // Allocate ScopeInfos for inner scopes.
2258 5401548 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2259 5632715 : if (!scope->is_function_scope() ||
2260 : scope->AsDeclarationScope()->ShouldEagerCompile()) {
2261 840890 : scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2262 : }
2263 : }
2264 2421928 : }
2265 :
2266 : // static
2267 1581036 : void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate) {
2268 : DeclarationScope* scope = info->literal()->scope();
2269 1581036 : if (!scope->scope_info_.is_null()) return; // Allocated by outer function.
2270 :
2271 1581036 : MaybeHandle<ScopeInfo> outer_scope;
2272 1581036 : if (scope->outer_scope_ != nullptr) {
2273 1426595 : outer_scope = scope->outer_scope_->scope_info_;
2274 : }
2275 :
2276 1581036 : scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2277 :
2278 : // The debugger expects all shared function infos to contain a scope info.
2279 : // Since the top-most scope will end up in a shared function info, make sure
2280 : // it has one, even if it doesn't need a scope info.
2281 : // TODO(jochen|yangguo): Remove this requirement.
2282 1581043 : if (scope->scope_info_.is_null()) {
2283 : scope->scope_info_ =
2284 956226 : ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2285 : }
2286 :
2287 : // Ensuring that the outer script scope has a scope info avoids having
2288 : // special case for native contexts vs other contexts.
2289 3162096 : if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2290 : info->script_scope()->scope_info_ =
2291 1068998 : handle(ScopeInfo::Empty(isolate), isolate);
2292 : }
2293 : }
2294 :
2295 90 : int Scope::ContextLocalCount() const {
2296 90 : if (num_heap_slots() == 0) return 0;
2297 : Variable* function =
2298 55 : is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2299 : bool is_function_var_in_context =
2300 55 : function != nullptr && function->IsContextSlot();
2301 55 : return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2302 55 : (is_function_var_in_context ? 1 : 0);
2303 : }
2304 :
2305 20111 : Variable* ClassScope::DeclarePrivateName(const AstRawString* name,
2306 : bool* was_added) {
2307 40222 : Variable* result = EnsureRareData()->private_name_map.Declare(
2308 : zone(), this, name, VariableMode::kConst, NORMAL_VARIABLE,
2309 : InitializationFlag::kNeedsInitialization,
2310 20111 : MaybeAssignedFlag::kMaybeAssigned, was_added);
2311 20111 : if (*was_added) {
2312 : locals_.Add(result);
2313 : }
2314 : result->ForceContextAllocation();
2315 20111 : return result;
2316 : }
2317 :
2318 0 : Variable* ClassScope::LookupLocalPrivateName(const AstRawString* name) {
2319 2916 : if (rare_data_ == nullptr) {
2320 : return nullptr;
2321 : }
2322 2916 : return rare_data_->private_name_map.Lookup(name);
2323 : }
2324 :
2325 369766 : UnresolvedList::Iterator ClassScope::GetUnresolvedPrivateNameTail() {
2326 369766 : if (rare_data_ == nullptr) {
2327 367551 : return UnresolvedList::Iterator();
2328 : }
2329 : return rare_data_->unresolved_private_names.end();
2330 : }
2331 :
2332 5789 : void ClassScope::ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail) {
2333 5789 : if (rare_data_ == nullptr ||
2334 : rare_data_->unresolved_private_names.end() == tail) {
2335 : return;
2336 : }
2337 :
2338 : bool tail_is_empty = tail == UnresolvedList::Iterator();
2339 480 : if (tail_is_empty) {
2340 : // If the saved tail is empty, the list used to be empty, so clear it.
2341 : rare_data_->unresolved_private_names.Clear();
2342 : } else {
2343 : rare_data_->unresolved_private_names.Rewind(tail);
2344 : }
2345 : }
2346 :
2347 363582 : void ClassScope::MigrateUnresolvedPrivateNameTail(
2348 : AstNodeFactory* ast_node_factory, UnresolvedList::Iterator tail) {
2349 363582 : if (rare_data_ == nullptr ||
2350 : rare_data_->unresolved_private_names.end() == tail) {
2351 362715 : return;
2352 : }
2353 : UnresolvedList migrated_names;
2354 :
2355 : // If the saved tail is empty, the list used to be empty, so we should
2356 : // migrate everything after the head.
2357 : bool tail_is_empty = tail == UnresolvedList::Iterator();
2358 : UnresolvedList::Iterator it =
2359 867 : tail_is_empty ? rare_data_->unresolved_private_names.begin() : tail;
2360 :
2361 1824 : for (; it != rare_data_->unresolved_private_names.end(); ++it) {
2362 957 : VariableProxy* proxy = *it;
2363 : VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
2364 : migrated_names.Add(copy);
2365 : }
2366 :
2367 : // Replace with the migrated copies.
2368 867 : if (tail_is_empty) {
2369 : rare_data_->unresolved_private_names.Clear();
2370 : } else {
2371 : rare_data_->unresolved_private_names.Rewind(tail);
2372 : }
2373 867 : rare_data_->unresolved_private_names.Append(std::move(migrated_names));
2374 : }
2375 :
2376 5556 : void ClassScope::AddUnresolvedPrivateName(VariableProxy* proxy) {
2377 : // During a reparse, already_resolved_ may be true here, because
2378 : // the class scope is deserialized while the function scope inside may
2379 : // be new.
2380 : DCHECK(!proxy->is_resolved());
2381 : DCHECK(proxy->IsPrivateName());
2382 : EnsureRareData()->unresolved_private_names.Add(proxy);
2383 5556 : }
2384 :
2385 509 : Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) {
2386 : DCHECK(!scope_info_.is_null());
2387 : DCHECK_NULL(LookupLocalPrivateName(name));
2388 : DisallowHeapAllocation no_gc;
2389 :
2390 509 : String name_handle = *name->string();
2391 : VariableMode mode;
2392 : InitializationFlag init_flag;
2393 : MaybeAssignedFlag maybe_assigned_flag;
2394 : int index = ScopeInfo::ContextSlotIndex(*scope_info_, name_handle, &mode,
2395 509 : &init_flag, &maybe_assigned_flag);
2396 509 : if (index < 0) {
2397 : return nullptr;
2398 : }
2399 :
2400 : DCHECK_EQ(mode, VariableMode::kConst);
2401 : DCHECK_EQ(init_flag, InitializationFlag::kNeedsInitialization);
2402 : DCHECK_EQ(maybe_assigned_flag, MaybeAssignedFlag::kMaybeAssigned);
2403 :
2404 : // Add the found private name to the map to speed up subsequent
2405 : // lookups for the same name.
2406 : bool was_added;
2407 491 : Variable* var = DeclarePrivateName(name, &was_added);
2408 : DCHECK(was_added);
2409 : var->AllocateTo(VariableLocation::CONTEXT, index);
2410 491 : return var;
2411 : }
2412 :
2413 524 : Variable* ClassScope::LookupPrivateName(VariableProxy* proxy) {
2414 : DCHECK(!proxy->is_resolved());
2415 :
2416 524 : for (Scope* scope = this; !scope->is_script_scope();
2417 : scope = scope->outer_scope_) {
2418 524 : if (!scope->is_class_scope()) continue; // Only search in class scopes
2419 : ClassScope* class_scope = scope->AsClassScope();
2420 : // Try finding it in the private name map first, if it can't be found,
2421 : // try the deseralized scope info.
2422 : Variable* var = class_scope->LookupLocalPrivateName(proxy->raw_name());
2423 1033 : if (var == nullptr && !class_scope->scope_info_.is_null()) {
2424 509 : var = class_scope->LookupPrivateNameInScopeInfo(proxy->raw_name());
2425 : }
2426 : return var;
2427 : }
2428 : return nullptr;
2429 : }
2430 :
2431 153414 : bool ClassScope::ResolvePrivateNames(ParseInfo* info) {
2432 153414 : if (rare_data_ == nullptr ||
2433 : rare_data_->unresolved_private_names.is_empty()) {
2434 : return true;
2435 : }
2436 :
2437 : UnresolvedList& list = rare_data_->unresolved_private_names;
2438 1015 : for (VariableProxy* proxy : list) {
2439 524 : Variable* var = LookupPrivateName(proxy);
2440 524 : if (var == nullptr) {
2441 : Scanner::Location loc = proxy->location();
2442 : info->pending_error_handler()->ReportMessageAt(
2443 : loc.beg_pos, loc.end_pos,
2444 : MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
2445 18 : kSyntaxError);
2446 : return false;
2447 : } else {
2448 : var->set_is_used();
2449 506 : proxy->BindTo(var);
2450 : }
2451 : }
2452 :
2453 : // By now all unresolved private names should be resolved so
2454 : // clear the list.
2455 : list.Clear();
2456 491 : return true;
2457 : }
2458 :
2459 166534 : VariableProxy* ClassScope::ResolvePrivateNamesPartially() {
2460 166534 : if (rare_data_ == nullptr ||
2461 : rare_data_->unresolved_private_names.is_empty()) {
2462 : return nullptr;
2463 : }
2464 :
2465 : ClassScope* outer_class_scope =
2466 2178 : outer_scope_ == nullptr ? nullptr : outer_scope_->GetClassScope();
2467 2178 : UnresolvedList& unresolved = rare_data_->unresolved_private_names;
2468 : bool has_private_names = rare_data_->private_name_map.capacity() > 0;
2469 :
2470 : // If the class itself does not have private names, nor does it have
2471 : // an outer class scope, then we are certain any private name access
2472 : // inside cannot be resolved.
2473 2178 : if (!has_private_names && outer_class_scope == nullptr &&
2474 : !unresolved.is_empty()) {
2475 0 : return unresolved.first();
2476 : }
2477 :
2478 2867 : for (VariableProxy* proxy = unresolved.first(); proxy != nullptr;) {
2479 : DCHECK(proxy->IsPrivateName());
2480 : VariableProxy* next = proxy->next_unresolved();
2481 2392 : unresolved.Remove(proxy);
2482 : Variable* var = nullptr;
2483 :
2484 : // If we can find private name in the current class scope, we can bind
2485 : // them immediately because it's going to shadow any outer private names.
2486 2392 : if (has_private_names) {
2487 : var = LookupLocalPrivateName(proxy->raw_name());
2488 2392 : if (var != nullptr) {
2489 : var->set_is_used();
2490 635 : proxy->BindTo(var);
2491 : }
2492 : }
2493 :
2494 : // If the current scope does not have declared private names,
2495 : // try looking from the outer class scope later.
2496 2392 : if (var == nullptr) {
2497 : // There's no outer class scope so we are certain that the variable
2498 : // cannot be resolved later.
2499 1757 : if (outer_class_scope == nullptr) {
2500 : return proxy;
2501 : }
2502 :
2503 : // The private name may be found later in the outer class scope,
2504 : // so push it to the outer sopce.
2505 54 : outer_class_scope->AddUnresolvedPrivateName(proxy);
2506 : }
2507 :
2508 : proxy = next;
2509 : }
2510 :
2511 : DCHECK(unresolved.is_empty());
2512 : return nullptr;
2513 : }
2514 :
2515 : } // namespace internal
2516 121996 : } // namespace v8
|