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 39808369 : Variable* VariableMap::Declare(Zone* zone, Scope* scope,
39 39808369 : 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 : ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
49 79618144 : ZoneAllocationPolicy(zone));
50 39809775 : *was_added = p->value == nullptr;
51 39809775 : 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 38650833 : p->value = variable;
57 : }
58 39808677 : return reinterpret_cast<Variable*>(p->value);
59 : }
60 :
61 3906 : void VariableMap::Remove(Variable* var) {
62 3906 : const AstRawString* name = var->raw_name();
63 3906 : ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
64 0 : }
65 :
66 995930 : void VariableMap::Add(Zone* zone, Variable* var) {
67 995930 : const AstRawString* name = var->raw_name();
68 : Entry* p =
69 : ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->Hash(),
70 1991888 : ZoneAllocationPolicy(zone));
71 : DCHECK_NULL(p->value);
72 : DCHECK_EQ(name, p->key);
73 995958 : p->value = var;
74 995958 : }
75 :
76 87736201 : Variable* VariableMap::Lookup(const AstRawString* name) {
77 87736201 : Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
78 87740183 : if (p != nullptr) {
79 : DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
80 : DCHECK_NOT_NULL(p->value);
81 38612663 : return reinterpret_cast<Variable*>(p->value);
82 : }
83 : return nullptr;
84 : }
85 :
86 : // ----------------------------------------------------------------------------
87 : // Implementation of Scope
88 :
89 2957967 : Scope::Scope(Zone* zone)
90 : : zone_(zone),
91 : outer_scope_(nullptr),
92 : variables_(zone),
93 5915936 : scope_type_(SCRIPT_SCOPE) {
94 : SetDefaults();
95 2957969 : }
96 :
97 12778630 : Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
98 : : zone_(zone),
99 : outer_scope_(outer_scope),
100 : variables_(zone),
101 25557654 : scope_type_(scope_type) {
102 : DCHECK_NE(SCRIPT_SCOPE, scope_type);
103 : SetDefaults();
104 : set_language_mode(outer_scope->language_mode());
105 12779024 : outer_scope_->AddInnerScope(this);
106 12779024 : }
107 :
108 2957966 : DeclarationScope::DeclarationScope(Zone* zone,
109 2957946 : AstValueFactory* ast_value_factory)
110 5915916 : : Scope(zone), function_kind_(kNormalFunction), params_(4, zone) {
111 : DCHECK_EQ(scope_type_, SCRIPT_SCOPE);
112 2957950 : SetDefaults();
113 : receiver_ = DeclareDynamicGlobal(ast_value_factory->this_string(),
114 2957946 : THIS_VARIABLE, this);
115 2957917 : }
116 :
117 6771202 : 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 13542862 : params_(4, zone) {
123 : DCHECK_NE(scope_type, SCRIPT_SCOPE);
124 6771660 : SetDefaults();
125 6771624 : }
126 :
127 71705 : ModuleScope::ModuleScope(DeclarationScope* script_scope,
128 143410 : AstValueFactory* ast_value_factory)
129 : : DeclarationScope(ast_value_factory->zone(), script_scope, MODULE_SCOPE,
130 71705 : kModule) {
131 : Zone* zone = ast_value_factory->zone();
132 71705 : module_descriptor_ = new (zone) ModuleDescriptor(zone);
133 : set_language_mode(LanguageMode::kStrict);
134 71705 : DeclareThis(ast_value_factory);
135 71705 : }
136 :
137 3218 : ModuleScope::ModuleScope(Isolate* isolate, Handle<ScopeInfo> scope_info,
138 6436 : AstValueFactory* avfactory)
139 3218 : : DeclarationScope(avfactory->zone(), MODULE_SCOPE, scope_info) {
140 : Zone* zone = avfactory->zone();
141 6436 : Handle<ModuleInfo> module_info(scope_info->ModuleDescriptorInfo(), isolate);
142 :
143 : set_language_mode(LanguageMode::kStrict);
144 3218 : module_descriptor_ = new (zone) ModuleDescriptor(zone);
145 :
146 : // Deserialize special exports.
147 6436 : Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
148 3218 : for (int i = 0, n = special_exports->length(); i < n; ++i) {
149 : Handle<ModuleInfoEntry> serialized_entry(
150 : ModuleInfoEntry::cast(special_exports->get(i)), isolate);
151 : module_descriptor_->AddSpecialExport(
152 : ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
153 0 : serialized_entry),
154 0 : avfactory->zone());
155 : }
156 :
157 : // Deserialize regular exports.
158 : module_descriptor_->DeserializeRegularExports(isolate, avfactory,
159 3218 : module_info);
160 :
161 : // Deserialize namespace imports.
162 : Handle<FixedArray> namespace_imports(module_info->namespace_imports(),
163 6436 : isolate);
164 3513 : for (int i = 0, n = namespace_imports->length(); i < n; ++i) {
165 : Handle<ModuleInfoEntry> serialized_entry(
166 : ModuleInfoEntry::cast(namespace_imports->get(i)), isolate);
167 : module_descriptor_->AddNamespaceImport(
168 : ModuleDescriptor::Entry::Deserialize(isolate, avfactory,
169 295 : serialized_entry),
170 295 : avfactory->zone());
171 : }
172 :
173 : // Deserialize regular imports.
174 6436 : Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
175 5699 : for (int i = 0, n = regular_imports->length(); i < n; ++i) {
176 : Handle<ModuleInfoEntry> serialized_entry(
177 : ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
178 : module_descriptor_->AddRegularImport(ModuleDescriptor::Entry::Deserialize(
179 2481 : isolate, avfactory, serialized_entry));
180 : }
181 3218 : }
182 :
183 1068541 : Scope::Scope(Zone* zone, ScopeType scope_type, Handle<ScopeInfo> scope_info)
184 : : zone_(zone),
185 : outer_scope_(nullptr),
186 : variables_(zone),
187 : scope_info_(scope_info),
188 2137084 : scope_type_(scope_type) {
189 : DCHECK(!scope_info.is_null());
190 : SetDefaults();
191 : #ifdef DEBUG
192 : already_resolved_ = true;
193 : #endif
194 1068544 : if (scope_info->CallsSloppyEval()) scope_calls_eval_ = true;
195 2137092 : set_language_mode(scope_info->language_mode());
196 1068546 : num_heap_slots_ = scope_info->ContextLength();
197 : DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_);
198 : // We don't really need to use the preparsed scope data; this is just to
199 : // shorten the recursion in SetMustUsePreparseData.
200 1068545 : must_use_preparsed_scope_data_ = true;
201 1068545 : }
202 :
203 898115 : DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
204 : Handle<ScopeInfo> scope_info)
205 : : Scope(zone, scope_type, scope_info),
206 1796228 : function_kind_(scope_info->function_kind()),
207 3592457 : params_(0, zone) {
208 : DCHECK_NE(scope_type, SCRIPT_SCOPE);
209 898114 : SetDefaults();
210 898114 : }
211 :
212 5294 : Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
213 : MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
214 : : zone_(zone),
215 : outer_scope_(nullptr),
216 : variables_(zone),
217 : scope_info_(scope_info),
218 10588 : scope_type_(CATCH_SCOPE) {
219 : SetDefaults();
220 : #ifdef DEBUG
221 : already_resolved_ = true;
222 : #endif
223 : // Cache the catch variable, even though it's also available via the
224 : // scope_info, as the parser expects that a catch scope always has the catch
225 : // variable as first and only variable.
226 : bool was_added;
227 : Variable* variable =
228 : Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
229 5294 : kCreatedInitialized, maybe_assigned, &was_added);
230 : DCHECK(was_added);
231 : AllocateHeapSlot(variable);
232 5294 : }
233 :
234 10627710 : void DeclarationScope::SetDefaults() {
235 10627710 : is_declaration_scope_ = true;
236 10627710 : has_simple_parameters_ = true;
237 10627710 : is_asm_module_ = false;
238 10627710 : force_eager_compilation_ = false;
239 10627710 : has_arguments_parameter_ = false;
240 10627710 : scope_uses_super_property_ = false;
241 10627710 : has_checked_syntax_ = false;
242 10627710 : has_this_reference_ = false;
243 : has_this_declaration_ =
244 17058519 : (is_function_scope() && !is_arrow_scope()) || is_module_scope();
245 10627710 : has_rest_ = false;
246 10627710 : receiver_ = nullptr;
247 10627710 : new_target_ = nullptr;
248 10627710 : function_ = nullptr;
249 10627710 : arguments_ = nullptr;
250 10627710 : rare_data_ = nullptr;
251 10627710 : should_eager_compile_ = false;
252 10627710 : was_lazily_parsed_ = false;
253 10627710 : is_skipped_function_ = false;
254 10627710 : preparse_data_builder_ = nullptr;
255 : #ifdef DEBUG
256 : DeclarationScope* outer_declaration_scope =
257 : outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
258 : is_being_lazily_parsed_ =
259 : outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
260 : : false;
261 : #endif
262 10627710 : }
263 :
264 0 : void Scope::SetDefaults() {
265 : #ifdef DEBUG
266 : scope_name_ = nullptr;
267 : already_resolved_ = false;
268 : needs_migration_ = false;
269 : #endif
270 16810830 : inner_scope_ = nullptr;
271 16810830 : sibling_ = nullptr;
272 : unresolved_list_.Clear();
273 :
274 16810830 : start_position_ = kNoSourcePosition;
275 16810830 : end_position_ = kNoSourcePosition;
276 :
277 16810830 : num_stack_slots_ = 0;
278 16810830 : num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
279 :
280 : set_language_mode(LanguageMode::kSloppy);
281 :
282 16810830 : scope_calls_eval_ = false;
283 16810830 : scope_nonlinear_ = false;
284 16810830 : is_hidden_ = false;
285 16810830 : is_debug_evaluate_scope_ = false;
286 :
287 16810830 : inner_scope_calls_eval_ = false;
288 16810830 : force_context_allocation_ = false;
289 16810830 : force_context_allocation_for_parameters_ = false;
290 :
291 16810830 : is_declaration_scope_ = false;
292 :
293 16810830 : must_use_preparsed_scope_data_ = false;
294 0 : }
295 :
296 430906 : bool Scope::HasSimpleParameters() {
297 : DeclarationScope* scope = GetClosureScope();
298 585124 : return !scope->is_function_scope() || scope->has_simple_parameters();
299 : }
300 :
301 716685 : void DeclarationScope::set_should_eager_compile() {
302 2510641 : should_eager_compile_ = !was_lazily_parsed_;
303 716685 : }
304 :
305 5847 : void DeclarationScope::set_is_asm_module() { is_asm_module_ = true; }
306 :
307 1785664 : bool Scope::IsAsmModule() const {
308 7440205 : return is_function_scope() && AsDeclarationScope()->is_asm_module();
309 : }
310 :
311 6309 : bool Scope::ContainsAsmModule() const {
312 6309 : if (IsAsmModule()) return true;
313 :
314 : // Check inner scopes recursively
315 2530 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
316 : // Don't check inner functions which won't be eagerly compiled.
317 4967 : if (!scope->is_function_scope() ||
318 : scope->AsDeclarationScope()->ShouldEagerCompile()) {
319 2106 : if (scope->ContainsAsmModule()) return true;
320 : }
321 : }
322 :
323 : return false;
324 : }
325 :
326 1005066 : Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
327 : ScopeInfo scope_info,
328 : DeclarationScope* script_scope,
329 : AstValueFactory* ast_value_factory,
330 : DeserializationMode deserialization_mode) {
331 : // Reconstruct the outer scope chain from a closure's context chain.
332 : Scope* current_scope = nullptr;
333 : Scope* innermost_scope = nullptr;
334 : Scope* outer_scope = nullptr;
335 3083971 : while (!scope_info.is_null()) {
336 1396860 : if (scope_info->scope_type() == WITH_SCOPE) {
337 14783 : if (scope_info->IsDebugEvaluateScope()) {
338 : outer_scope = new (zone)
339 25370 : DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
340 : outer_scope->set_is_debug_evaluate_scope();
341 : } else {
342 : // For scope analysis, debug-evaluate is equivalent to a with scope.
343 : outer_scope =
344 4196 : new (zone) Scope(zone, WITH_SCOPE, handle(scope_info, isolate));
345 : }
346 :
347 1382078 : } else if (scope_info->scope_type() == SCRIPT_SCOPE) {
348 : // If we reach a script scope, it's the outermost scope. Install the
349 : // scope info of this script context onto the existing script scope to
350 : // avoid nesting script scopes.
351 323023 : if (deserialization_mode == DeserializationMode::kIncludingVariables) {
352 : script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
353 : }
354 : DCHECK(!scope_info->HasOuterScopeInfo());
355 : break;
356 1059056 : } else if (scope_info->scope_type() == FUNCTION_SCOPE) {
357 : outer_scope = new (zone)
358 1694158 : DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info, isolate));
359 847079 : if (scope_info->IsAsmModule()) {
360 : outer_scope->AsDeclarationScope()->set_is_asm_module();
361 : }
362 211977 : } else if (scope_info->scope_type() == EVAL_SCOPE) {
363 : outer_scope = new (zone)
364 52836 : DeclarationScope(zone, EVAL_SCOPE, handle(scope_info, isolate));
365 185558 : } else if (scope_info->scope_type() == BLOCK_SCOPE) {
366 177045 : if (scope_info->is_declaration_scope()) {
367 : outer_scope = new (zone)
368 17430 : DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
369 : } else {
370 : outer_scope =
371 336663 : new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info, isolate));
372 : }
373 8512 : } else if (scope_info->scope_type() == MODULE_SCOPE) {
374 : outer_scope = new (zone)
375 6436 : ModuleScope(isolate, handle(scope_info, isolate), ast_value_factory);
376 : } else {
377 : DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE);
378 : DCHECK_EQ(scope_info->ContextLocalCount(), 1);
379 : DCHECK_EQ(scope_info->ContextLocalMode(0), VariableMode::kVar);
380 : DCHECK_EQ(scope_info->ContextLocalInitFlag(0), kCreatedInitialized);
381 5294 : String name = scope_info->ContextLocalName(0);
382 : MaybeAssignedFlag maybe_assigned =
383 5294 : scope_info->ContextLocalMaybeAssignedFlag(0);
384 : outer_scope = new (zone)
385 : Scope(zone, ast_value_factory->GetString(handle(name, isolate)),
386 15882 : maybe_assigned, handle(scope_info, isolate));
387 : }
388 1073839 : if (deserialization_mode == DeserializationMode::kScopesOnly) {
389 0 : outer_scope->scope_info_ = Handle<ScopeInfo>::null();
390 : }
391 1073839 : if (current_scope != nullptr) {
392 : outer_scope->AddInnerScope(current_scope);
393 : }
394 : current_scope = outer_scope;
395 1073839 : if (innermost_scope == nullptr) innermost_scope = current_scope;
396 1073839 : scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo()
397 1073837 : : ScopeInfo();
398 : }
399 :
400 2010136 : if (deserialization_mode == DeserializationMode::kIncludingVariables &&
401 : script_scope->scope_info_.is_null()) {
402 : Handle<ScriptContextTable> table(
403 2046135 : isolate->native_context()->script_context_table(), isolate);
404 682045 : Handle<Context> first = ScriptContextTable::GetContext(isolate, table, 0);
405 1364090 : Handle<ScopeInfo> scope_info(first->scope_info(), isolate);
406 : script_scope->SetScriptScopeInfo(scope_info);
407 : }
408 :
409 1005068 : if (innermost_scope == nullptr) return script_scope;
410 849568 : script_scope->AddInnerScope(current_scope);
411 849568 : return innermost_scope;
412 : }
413 :
414 150346443 : DeclarationScope* Scope::AsDeclarationScope() {
415 : DCHECK(is_declaration_scope());
416 150346443 : return static_cast<DeclarationScope*>(this);
417 : }
418 :
419 0 : const DeclarationScope* Scope::AsDeclarationScope() const {
420 : DCHECK(is_declaration_scope());
421 0 : return static_cast<const DeclarationScope*>(this);
422 : }
423 :
424 55221 : ModuleScope* Scope::AsModuleScope() {
425 : DCHECK(is_module_scope());
426 55221 : return static_cast<ModuleScope*>(this);
427 : }
428 :
429 0 : const ModuleScope* Scope::AsModuleScope() const {
430 : DCHECK(is_module_scope());
431 0 : return static_cast<const ModuleScope*>(this);
432 : }
433 :
434 11609 : void DeclarationScope::DeclareSloppyBlockFunction(
435 : SloppyBlockFunctionStatement* sloppy_block_function) {
436 : sloppy_block_functions_.Add(sloppy_block_function);
437 11609 : }
438 :
439 5107435 : void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
440 : DCHECK(is_sloppy(language_mode()));
441 : DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||
442 : (is_block_scope() && outer_scope()->is_function_scope()));
443 : DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_);
444 : DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_);
445 :
446 10154897 : if (sloppy_block_functions_.is_empty()) return;
447 :
448 : // In case of complex parameters the current scope is the body scope and the
449 : // parameters are stored in the outer scope.
450 10233 : Scope* parameter_scope = HasSimpleParameters() ? this : outer_scope_;
451 : DCHECK(parameter_scope->is_function_scope() || is_eval_scope() ||
452 : is_script_scope());
453 :
454 : DeclarationScope* decl_scope = this;
455 21828 : while (decl_scope->is_eval_scope()) {
456 23190 : decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
457 : }
458 : Scope* outer_scope = decl_scope->outer_scope();
459 :
460 : // For each variable which is used as a function declaration in a sloppy
461 : // block,
462 60875 : for (SloppyBlockFunctionStatement* sloppy_block_function :
463 21736 : sloppy_block_functions_) {
464 : const AstRawString* name = sloppy_block_function->name();
465 :
466 : // If the variable wouldn't conflict with a lexical declaration
467 : // or parameter,
468 :
469 : // Check if there's a conflict with a parameter.
470 : Variable* maybe_parameter = parameter_scope->LookupLocal(name);
471 14280 : if (maybe_parameter != nullptr && maybe_parameter->is_parameter()) {
472 : continue;
473 : }
474 :
475 : // Check if there's a conflict with a lexical declaration
476 26102 : Scope* query_scope = sloppy_block_function->scope()->outer_scope();
477 3258 : Variable* var = nullptr;
478 : bool should_hoist = true;
479 :
480 : // It is not sufficient to just do a Lookup on query_scope: for
481 : // example, that does not prevent hoisting of the function in
482 : // `{ let e; try {} catch (e) { function e(){} } }`
483 14791 : do {
484 16197 : var = query_scope->LookupInScopeOrScopeInfo(name);
485 19455 : if (var != nullptr && IsLexicalVariableMode(var->mode())) {
486 : should_hoist = false;
487 : break;
488 : }
489 : query_scope = query_scope->outer_scope();
490 : } while (query_scope != outer_scope);
491 :
492 11311 : if (!should_hoist) continue;
493 :
494 9905 : if (factory) {
495 : DCHECK(!is_being_lazily_parsed_);
496 7497 : int pos = sloppy_block_function->position();
497 7497 : bool ok = true;
498 : bool was_added;
499 : auto declaration = factory->NewVariableDeclaration(pos);
500 : // Based on the preceding checks, it doesn't matter what we pass as
501 : // sloppy_mode_block_scope_function_redefinition.
502 : Variable* var = DeclareVariable(
503 : declaration, name, pos, VariableMode::kVar, NORMAL_VARIABLE,
504 : Variable::DefaultInitializationFlag(VariableMode::kVar), &was_added,
505 7497 : nullptr, &ok);
506 : DCHECK(ok);
507 : VariableProxy* source =
508 : factory->NewVariableProxy(sloppy_block_function->var());
509 : VariableProxy* target = factory->NewVariableProxy(var);
510 : Assignment* assignment = factory->NewAssignment(
511 7497 : sloppy_block_function->init(), target, source, pos);
512 : assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
513 : Statement* statement = factory->NewExpressionStatement(assignment, pos);
514 : sloppy_block_function->set_statement(statement);
515 : } else {
516 : DCHECK(is_being_lazily_parsed_);
517 : bool was_added;
518 2408 : Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
519 2408 : if (sloppy_block_function->init() == Token::ASSIGN)
520 : var->set_maybe_assigned();
521 : }
522 : }
523 : }
524 :
525 5381862 : bool DeclarationScope::Analyze(ParseInfo* info) {
526 : RuntimeCallTimerScope runtimeTimer(
527 : info->runtime_call_stats(),
528 : info->on_background_thread()
529 : ? RuntimeCallCounterId::kCompileBackgroundScopeAnalysis
530 3587906 : : RuntimeCallCounterId::kCompileScopeAnalysis);
531 : DCHECK_NOT_NULL(info->literal());
532 1793956 : DeclarationScope* scope = info->literal()->scope();
533 :
534 : base::Optional<AllowHandleDereference> allow_deref;
535 : if (!info->maybe_outer_scope_info().is_null()) {
536 : // Allow dereferences to the scope info if there is one.
537 : allow_deref.emplace();
538 : }
539 :
540 2646654 : if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
541 726710 : AstNodeFactory factory(info->ast_value_factory(), info->zone());
542 726710 : scope->HoistSloppyBlockFunctions(&factory);
543 : }
544 :
545 : // We are compiling one of four cases:
546 : // 1) top-level code,
547 : // 2) a function/eval/module on the top-level
548 : // 3) a function/eval in a scope that was already resolved.
549 : DCHECK(scope->is_script_scope() || scope->outer_scope()->is_script_scope() ||
550 : scope->outer_scope()->already_resolved_);
551 :
552 : // The outer scope is never lazy.
553 : scope->set_should_eager_compile();
554 :
555 1793956 : if (scope->must_use_preparsed_scope_data_) {
556 : DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE);
557 : allow_deref.emplace();
558 36349 : info->consumed_preparse_data()->RestoreScopeAllocationData(scope);
559 : }
560 :
561 1793956 : if (!scope->AllocateVariables(info)) return false;
562 :
563 : #ifdef DEBUG
564 : if (info->is_native() ? FLAG_print_builtin_scopes : FLAG_print_scopes) {
565 : PrintF("Global scope:\n");
566 : scope->Print();
567 : }
568 : scope->CheckScopePositions();
569 : scope->CheckZones();
570 : #endif
571 :
572 1793784 : return true;
573 : }
574 :
575 10438866 : void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
576 : DCHECK(has_this_declaration());
577 :
578 5219433 : bool derived_constructor = IsDerivedConstructor(function_kind_);
579 :
580 5219433 : receiver_ = new (zone())
581 : Variable(this, ast_value_factory->this_string(),
582 : derived_constructor ? VariableMode::kConst : VariableMode::kVar,
583 : THIS_VARIABLE,
584 : derived_constructor ? kNeedsInitialization : kCreatedInitialized,
585 10438934 : kNotAssigned);
586 5219467 : }
587 :
588 4074728 : void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
589 : DCHECK(is_function_scope());
590 : DCHECK(!is_arrow_scope());
591 :
592 : // Declare 'arguments' variable which exists in all non arrow functions. Note
593 : // that it might never be accessed, in which case it won't be allocated during
594 : // variable allocation.
595 : bool was_added;
596 : arguments_ =
597 : Declare(zone(), ast_value_factory->arguments_string(), VariableMode::kVar,
598 4074728 : NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
599 4077561 : if (!was_added && IsLexicalVariableMode(arguments_->mode())) {
600 : // Check if there's lexically declared variable named arguments to avoid
601 : // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
602 622 : arguments_ = nullptr;
603 : }
604 4074800 : }
605 :
606 4509483 : void DeclarationScope::DeclareDefaultFunctionVariables(
607 6336226 : AstValueFactory* ast_value_factory) {
608 : DCHECK(is_function_scope());
609 : DCHECK(!is_arrow_scope());
610 :
611 4509483 : DeclareThis(ast_value_factory);
612 : bool was_added;
613 : new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
614 : VariableMode::kConst, NORMAL_VARIABLE,
615 5422852 : kCreatedInitialized, kNotAssigned, &was_added);
616 : DCHECK(was_added);
617 :
618 16574872 : if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
619 : IsAccessorFunction(function_kind_)) {
620 : EnsureRareData()->this_function = Declare(
621 : zone(), ast_value_factory->this_function_string(), VariableMode::kConst,
622 913369 : NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
623 : DCHECK(was_added);
624 : }
625 4509474 : }
626 :
627 996835 : Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
628 : Scope* cache) {
629 : DCHECK(is_function_scope());
630 : DCHECK_NULL(function_);
631 996835 : if (cache == nullptr) cache = this;
632 : DCHECK_NULL(cache->variables_.Lookup(name));
633 1992764 : VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
634 996835 : : NORMAL_VARIABLE;
635 : function_ = new (zone())
636 1993656 : Variable(this, name, VariableMode::kConst, kind, kCreatedInitialized);
637 996828 : if (calls_sloppy_eval()) {
638 899 : cache->NonLocal(name, VariableMode::kDynamic);
639 : } else {
640 995929 : cache->variables_.Add(zone(), function_);
641 : }
642 996857 : return function_;
643 : }
644 :
645 142688 : Variable* DeclarationScope::DeclareGeneratorObjectVar(
646 142688 : const AstRawString* name) {
647 : DCHECK(is_function_scope() || is_module_scope());
648 : DCHECK_NULL(generator_object_var());
649 :
650 : Variable* result = EnsureRareData()->generator_object =
651 142689 : NewTemporary(name, kNotAssigned);
652 : result->set_is_used();
653 142688 : return result;
654 : }
655 :
656 14761245 : Scope* Scope::FinalizeBlockScope() {
657 : DCHECK(is_block_scope());
658 : #ifdef DEBUG
659 : DCHECK_NE(sibling_, this);
660 : #endif
661 :
662 14678873 : if (variables_.occupancy() > 0 ||
663 68171 : (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval())) {
664 : return this;
665 : }
666 :
667 : // Remove this scope from outer scope.
668 : outer_scope()->RemoveInnerScope(this);
669 :
670 : // Reparent inner scopes.
671 4379370 : if (inner_scope_ != nullptr) {
672 : Scope* scope = inner_scope_;
673 541976 : scope->outer_scope_ = outer_scope();
674 1125857 : while (scope->sibling_ != nullptr) {
675 : scope = scope->sibling_;
676 41905 : scope->outer_scope_ = outer_scope();
677 : }
678 541976 : scope->sibling_ = outer_scope()->inner_scope_;
679 541976 : outer_scope()->inner_scope_ = inner_scope_;
680 541976 : inner_scope_ = nullptr;
681 : }
682 :
683 : // Move unresolved variables
684 4379370 : if (!unresolved_list_.is_empty()) {
685 : outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
686 : unresolved_list_.Clear();
687 : }
688 :
689 4474844 : if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
690 :
691 : // No need to propagate scope_calls_eval_, since if it was relevant to
692 : // this scope we would have had to bail out at the top.
693 : DCHECK(!scope_calls_eval_ || !is_declaration_scope() ||
694 : !is_sloppy(language_mode()));
695 :
696 : // This block does not need a context.
697 4379370 : num_heap_slots_ = 0;
698 :
699 : // Mark scope as removed by making it its own sibling.
700 : #ifdef DEBUG
701 : sibling_ = this;
702 : #endif
703 :
704 4379370 : return nullptr;
705 : }
706 :
707 0 : void DeclarationScope::AddLocal(Variable* var) {
708 : DCHECK(!already_resolved_);
709 : // Temporaries are only placed in ClosureScopes.
710 : DCHECK_EQ(GetClosureScope(), this);
711 : locals_.Add(var);
712 0 : }
713 :
714 132572 : void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
715 : DCHECK(!IsCleared());
716 : DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
717 : DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
718 : DCHECK_EQ(new_parent, new_parent->GetClosureScope());
719 : DCHECK_NULL(new_parent->inner_scope_);
720 : DCHECK(new_parent->unresolved_list_.is_empty());
721 132572 : Scope* inner_scope = new_parent->sibling_;
722 132572 : if (inner_scope != top_inner_scope_) {
723 3644 : for (; inner_scope->sibling() != top_inner_scope_;
724 : inner_scope = inner_scope->sibling()) {
725 0 : inner_scope->outer_scope_ = new_parent;
726 0 : if (inner_scope->inner_scope_calls_eval_) {
727 0 : new_parent->inner_scope_calls_eval_ = true;
728 : }
729 : DCHECK_NE(inner_scope, new_parent);
730 : }
731 3644 : inner_scope->outer_scope_ = new_parent;
732 3644 : if (inner_scope->inner_scope_calls_eval_) {
733 128 : new_parent->inner_scope_calls_eval_ = true;
734 : }
735 3644 : new_parent->inner_scope_ = new_parent->sibling_;
736 3644 : inner_scope->sibling_ = nullptr;
737 : // Reset the sibling rather than the inner_scope_ since we
738 : // want to keep new_parent there.
739 3644 : new_parent->sibling_ = top_inner_scope_;
740 : }
741 :
742 : Scope* outer_scope_ = outer_scope_and_calls_eval_.GetPointer();
743 : new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
744 : top_unresolved_);
745 :
746 : // Move temporaries allocated for complex parameter initializers.
747 : DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
748 265156 : for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
749 12 : Variable* local = *it;
750 : DCHECK_EQ(VariableMode::kTemporary, local->mode());
751 : DCHECK_EQ(local->scope(), local->scope()->GetClosureScope());
752 : DCHECK_NE(local->scope(), new_parent);
753 : local->set_scope(new_parent);
754 : }
755 : new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
756 : outer_closure->locals_.Rewind(top_local_);
757 :
758 : // Move eval calls since Snapshot's creation into new_parent.
759 132572 : if (outer_scope_and_calls_eval_->scope_calls_eval_) {
760 419 : new_parent->scope_calls_eval_ = true;
761 419 : new_parent->inner_scope_calls_eval_ = true;
762 : }
763 :
764 : // We are in the arrow function case. The calls eval we may have recorded
765 : // is intended for the inner scope and we should simply restore the
766 : // original "calls eval" flag of the outer scope.
767 : RestoreEvalFlag();
768 : Clear();
769 132572 : }
770 :
771 91 : void Scope::ReplaceOuterScope(Scope* outer) {
772 : DCHECK_NOT_NULL(outer);
773 : DCHECK_NOT_NULL(outer_scope_);
774 : DCHECK(!already_resolved_);
775 91 : outer_scope_->RemoveInnerScope(this);
776 : outer->AddInnerScope(this);
777 : outer_scope_ = outer;
778 91 : }
779 :
780 4906822 : Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
781 : DCHECK(!scope_info_.is_null());
782 : DCHECK_NULL(cache->variables_.Lookup(name));
783 : DisallowHeapAllocation no_gc;
784 :
785 2453197 : String name_handle = *name->string();
786 : // The Scope is backed up by ScopeInfo. This means it cannot operate in a
787 : // heap-independent mode, and all strings must be internalized immediately. So
788 : // it's ok to get the Handle<String> here.
789 : bool found = false;
790 :
791 : VariableLocation location;
792 : int index;
793 : VariableMode mode;
794 : InitializationFlag init_flag;
795 : MaybeAssignedFlag maybe_assigned_flag;
796 :
797 : {
798 : location = VariableLocation::CONTEXT;
799 : index = ScopeInfo::ContextSlotIndex(*scope_info_, name_handle, &mode,
800 2453198 : &init_flag, &maybe_assigned_flag);
801 2453199 : found = index >= 0;
802 : }
803 :
804 4459132 : if (!found && is_module_scope()) {
805 : location = VariableLocation::MODULE;
806 : index = scope_info_->ModuleIndex(name_handle, &mode, &init_flag,
807 1981 : &maybe_assigned_flag);
808 1981 : found = index != 0;
809 : }
810 :
811 2453199 : if (!found) {
812 2005506 : index = scope_info_->FunctionContextSlotIndex(name_handle);
813 2005505 : if (index < 0) return nullptr; // Nowhere found.
814 1040 : Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
815 : DCHECK_EQ(VariableMode::kConst, var->mode());
816 : var->AllocateTo(VariableLocation::CONTEXT, index);
817 1040 : return cache->variables_.Lookup(name);
818 : }
819 :
820 : if (!is_module_scope()) {
821 : DCHECK_NE(index, scope_info_->ReceiverContextSlotIndex());
822 : }
823 :
824 : bool was_added;
825 : Variable* var =
826 : cache->variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
827 895390 : init_flag, maybe_assigned_flag, &was_added);
828 : DCHECK(was_added);
829 : var->AllocateTo(location, index);
830 447694 : return var;
831 : }
832 :
833 2916459 : Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
834 : VariableMode mode,
835 : bool is_optional, bool is_rest,
836 2916472 : AstValueFactory* ast_value_factory,
837 : int position) {
838 : DCHECK(!already_resolved_);
839 : DCHECK(is_function_scope() || is_module_scope());
840 : DCHECK(!has_rest_);
841 : DCHECK(!is_optional || !is_rest);
842 : DCHECK(!is_being_lazily_parsed_);
843 : DCHECK(!was_lazily_parsed_);
844 : Variable* var;
845 2916459 : if (mode == VariableMode::kTemporary) {
846 3141360 : var = NewTemporary(name);
847 : } else {
848 2804020 : var = LookupLocal(name);
849 : DCHECK_EQ(mode, VariableMode::kVar);
850 : DCHECK(var->is_parameter());
851 : }
852 2916467 : has_rest_ = is_rest;
853 2916467 : var->set_initializer_position(position);
854 2916467 : params_.Add(var, zone());
855 2916472 : if (!is_rest) ++num_parameters_;
856 2916472 : if (name == ast_value_factory->arguments_string()) {
857 1454 : has_arguments_parameter_ = true;
858 : }
859 : // Params are automatically marked as used to make sure that the debugger and
860 : // function.arguments sees them.
861 : // TODO(verwaest): Reevaluate whether we always need to do this, since
862 : // strict-mode function.arguments does not make the arguments available.
863 2916472 : var->set_is_used();
864 2916472 : return var;
865 : }
866 :
867 3918536 : void DeclarationScope::RecordParameter(bool is_rest) {
868 : DCHECK(!already_resolved_);
869 : DCHECK(is_function_scope() || is_module_scope());
870 : DCHECK(is_being_lazily_parsed_);
871 : DCHECK(!has_rest_);
872 3918536 : has_rest_ = is_rest;
873 3918536 : if (!is_rest) ++num_parameters_;
874 3918536 : }
875 :
876 23850270 : Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
877 : VariableKind kind, bool* was_added,
878 47701042 : InitializationFlag init_flag) {
879 : DCHECK(!already_resolved_);
880 : // This function handles VariableMode::kVar, VariableMode::kLet, and
881 : // VariableMode::kConst modes. VariableMode::kDynamic variables are
882 : // introduced during variable allocation, and VariableMode::kTemporary
883 : // variables are allocated via NewTemporary().
884 : DCHECK(IsDeclaredVariableMode(mode));
885 : DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),
886 : mode == VariableMode::kVar || mode == VariableMode::kLet ||
887 : mode == VariableMode::kConst);
888 : DCHECK(!GetDeclarationScope()->was_lazily_parsed());
889 : Variable* var =
890 47700540 : Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);
891 :
892 : // Pessimistically assume that top-level variables will be assigned and used.
893 : //
894 : // Top-level variables in a script can be accessed by other scripts or even
895 : // become global properties. While this does not apply to top-level variables
896 : // in a module (assuming they are not exported), we must still mark these as
897 : // assigned because they might be accessed by a lazily parsed top-level
898 : // function, which, for efficiency, we preparse without variable tracking.
899 23850772 : if (is_script_scope() || is_module_scope()) {
900 4045911 : if (mode != VariableMode::kConst) var->set_maybe_assigned();
901 : var->set_is_used();
902 : }
903 :
904 23850772 : return var;
905 : }
906 :
907 15667950 : Variable* Scope::DeclareVariable(
908 : Declaration* declaration, const AstRawString* name, int pos,
909 : VariableMode mode, VariableKind kind, InitializationFlag init,
910 : bool* was_added, bool* sloppy_mode_block_scope_function_redefinition,
911 13652639 : bool* ok) {
912 : DCHECK(IsDeclaredVariableMode(mode));
913 : DCHECK(!already_resolved_);
914 : DCHECK(!GetDeclarationScope()->is_being_lazily_parsed());
915 : DCHECK(!GetDeclarationScope()->was_lazily_parsed());
916 :
917 29648589 : if (mode == VariableMode::kVar && !is_declaration_scope()) {
918 : return GetDeclarationScope()->DeclareVariable(
919 : declaration, name, pos, mode, kind, init, was_added,
920 801036 : sloppy_mode_block_scope_function_redefinition, ok);
921 : }
922 : DCHECK(!is_catch_scope());
923 : DCHECK(!is_with_scope());
924 : DCHECK(is_declaration_scope() ||
925 : (IsLexicalVariableMode(mode) && is_block_scope()));
926 :
927 : DCHECK_NOT_NULL(name);
928 :
929 : Variable* var = LookupLocal(name);
930 : // Declare the variable in the declaration scope.
931 15267552 : *was_added = var == nullptr;
932 15267552 : if (V8_LIKELY(*was_added)) {
933 14464086 : if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&
934 : mode == VariableMode::kVar)) {
935 : // In a var binding in a sloppy direct eval, pollute the enclosing scope
936 : // with this new binding by doing the following:
937 : // The proxy is bound to a lookup variable to force a dynamic declaration
938 : // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
939 : DCHECK_EQ(NORMAL_VARIABLE, kind);
940 307430 : var = NonLocal(name, VariableMode::kDynamic);
941 : // Mark the var as used in case anyone outside the eval wants to use it.
942 : var->set_is_used();
943 : } else {
944 : // Declare the name.
945 13345209 : var = DeclareLocal(name, mode, kind, was_added, init);
946 : DCHECK(*was_added);
947 : }
948 : } else {
949 : var->set_maybe_assigned();
950 3179528 : if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||
951 : IsLexicalVariableMode(var->mode()))) {
952 : // The name was declared in this scope before; check for conflicting
953 : // re-declarations. We have a conflict if either of the declarations is
954 : // not a var (in script scope, we also have to ignore legacy const for
955 : // compatibility). There is similar code in runtime.cc in the Declare
956 : // functions. The function CheckConflictingVarDeclarations checks for
957 : // var and let bindings from different scopes whereas this is a check
958 : // for conflicting declarations within the same scope. This check also
959 : // covers the special case
960 : //
961 : // function () { let x; { var x; } }
962 : //
963 : // because the var declaration is hoisted to the function scope where
964 : // 'x' is already bound.
965 : //
966 : // In harmony we treat re-declarations as early errors. See ES5 16 for a
967 : // definition of early errors.
968 : //
969 : // Allow duplicate function decls for web compat, see bug 4693.
970 64459 : *ok = var->is_sloppy_block_function() &&
971 64459 : kind == SLOPPY_BLOCK_FUNCTION_VARIABLE;
972 64459 : *sloppy_mode_block_scope_function_redefinition = *ok;
973 : }
974 : }
975 : DCHECK_NOT_NULL(var);
976 :
977 : // We add a declaration node for every declaration. The compiler
978 : // will only generate code if necessary. In particular, declarations
979 : // for inner local variables that do not represent functions won't
980 : // result in any generated code.
981 : //
982 : // This will lead to multiple declaration nodes for the
983 : // same variable if it is declared several times. This is not a
984 : // semantic issue, but it may be a performance issue since it may
985 : // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
986 : decls_.Add(declaration);
987 : declaration->set_var(var);
988 15267655 : return var;
989 : }
990 :
991 10955744 : Variable* Scope::DeclareVariableName(const AstRawString* name,
992 : VariableMode mode, bool* was_added,
993 : VariableKind kind) {
994 : DCHECK(IsDeclaredVariableMode(mode));
995 : DCHECK(!already_resolved_);
996 : DCHECK(GetDeclarationScope()->is_being_lazily_parsed());
997 :
998 20506341 : if (mode == VariableMode::kVar && !is_declaration_scope()) {
999 : return GetDeclarationScope()->DeclareVariableName(name, mode, was_added,
1000 1120546 : kind);
1001 : }
1002 : DCHECK(!is_with_scope());
1003 : DCHECK(!is_eval_scope());
1004 : DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode));
1005 : DCHECK(scope_info_.is_null());
1006 :
1007 : // Declare the variable in the declaration scope.
1008 11263160 : Variable* var = DeclareLocal(name, mode, kind, was_added);
1009 10395972 : if (!*was_added) {
1010 1736076 : if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) {
1011 712 : if (!var->is_sloppy_block_function() ||
1012 : kind != SLOPPY_BLOCK_FUNCTION_VARIABLE) {
1013 : // Duplicate functions are allowed in the sloppy mode, but if this is
1014 : // not a function declaration, it's an error. This is an error PreParser
1015 : // hasn't previously detected.
1016 : return nullptr;
1017 : }
1018 : // Sloppy block function redefinition.
1019 : }
1020 : var->set_maybe_assigned();
1021 : }
1022 : var->set_is_used();
1023 10395366 : return var;
1024 : }
1025 :
1026 365645 : Variable* Scope::DeclareCatchVariableName(const AstRawString* name) {
1027 : DCHECK(!already_resolved_);
1028 : DCHECK(is_catch_scope());
1029 : DCHECK(scope_info_.is_null());
1030 :
1031 : bool was_added;
1032 : Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE,
1033 365645 : kCreatedInitialized, kNotAssigned, &was_added);
1034 : DCHECK(was_added);
1035 365813 : return result;
1036 : }
1037 :
1038 50041632 : void Scope::AddUnresolved(VariableProxy* proxy) {
1039 : DCHECK(!already_resolved_);
1040 : DCHECK(!proxy->is_resolved());
1041 : unresolved_list_.Add(proxy);
1042 50040895 : }
1043 :
1044 4919671 : Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1045 : VariableKind kind,
1046 : Scope* cache) {
1047 : DCHECK(is_script_scope());
1048 : bool was_added;
1049 : return cache->variables_.Declare(
1050 : zone(), this, name, VariableMode::kDynamicGlobal, kind,
1051 4919671 : kCreatedInitialized, kNotAssigned, &was_added);
1052 : // TODO(neis): Mark variable as maybe-assigned?
1053 : }
1054 :
1055 1289 : bool Scope::RemoveUnresolved(VariableProxy* var) {
1056 1289 : return unresolved_list_.Remove(var);
1057 : }
1058 :
1059 15713 : void Scope::DeleteUnresolved(VariableProxy* var) {
1060 : DCHECK(unresolved_list_.Contains(var));
1061 : var->mark_removed_from_unresolved();
1062 15713 : }
1063 :
1064 1228083 : Variable* Scope::NewTemporary(const AstRawString* name) {
1065 1340529 : return NewTemporary(name, kMaybeAssigned);
1066 : }
1067 :
1068 1483228 : Variable* Scope::NewTemporary(const AstRawString* name,
1069 1483228 : MaybeAssignedFlag maybe_assigned) {
1070 : DeclarationScope* scope = GetClosureScope();
1071 : Variable* var = new (zone()) Variable(scope, name, VariableMode::kTemporary,
1072 : NORMAL_VARIABLE, kCreatedInitialized);
1073 : scope->AddLocal(var);
1074 1483229 : if (maybe_assigned == kMaybeAssigned) var->set_maybe_assigned();
1075 1483229 : return var;
1076 : }
1077 :
1078 6534902 : Declaration* DeclarationScope::CheckConflictingVarDeclarations() {
1079 6534902 : if (has_checked_syntax_) return nullptr;
1080 26881484 : for (Declaration* decl : decls_) {
1081 : // Lexical vs lexical conflicts within the same scope have already been
1082 : // captured in Parser::Declare. The only conflicts we still need to check
1083 : // are lexical vs nested var.
1084 24795263 : if (decl->IsVariableDeclaration() &&
1085 11957906 : decl->AsVariableDeclaration()->AsNested() != nullptr) {
1086 3184715 : Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
1087 : DCHECK(decl->var()->mode() == VariableMode::kVar ||
1088 : decl->var()->mode() == VariableMode::kDynamic);
1089 : // Iterate through all scopes until the declaration scope.
1090 1327853 : do {
1091 : // There is a conflict if there exists a non-VAR binding.
1092 1340984 : if (current->is_catch_scope()) {
1093 : current = current->outer_scope();
1094 2780 : continue;
1095 : }
1096 1338204 : Variable* other_var = current->LookupLocal(decl->var()->raw_name());
1097 1338200 : if (other_var != nullptr) {
1098 : DCHECK(IsLexicalVariableMode(other_var->mode()));
1099 : return decl;
1100 : }
1101 : current = current->outer_scope();
1102 7674054 : } while (current != this);
1103 : }
1104 : }
1105 :
1106 6346201 : if (V8_LIKELY(!is_eval_scope())) return nullptr;
1107 854475 : if (!is_sloppy(language_mode())) return nullptr;
1108 :
1109 : // Var declarations in sloppy eval are hoisted to the first non-eval
1110 : // declaration scope. Check for conflicts between the eval scope that
1111 : // declaration scope.
1112 1454802 : Scope* end = this;
1113 727404 : do {
1114 727404 : end = end->outer_scope_->GetDeclarationScope();
1115 : } while (end->is_eval_scope());
1116 727398 : end = end->outer_scope_;
1117 :
1118 2045173 : for (Declaration* decl : decls_) {
1119 601778 : if (IsLexicalVariableMode(decl->var()->mode())) continue;
1120 578922 : Scope* current = outer_scope_;
1121 : // Iterate through all scopes until and including the declaration scope.
1122 289488 : do {
1123 : // There is a conflict if there exists a non-VAR binding up to the
1124 : // declaration scope in which this sloppy-eval runs.
1125 560 : Variable* other_var =
1126 289641 : current->LookupInScopeOrScopeInfo(decl->var()->raw_name());
1127 290201 : if (other_var != nullptr && IsLexicalVariableMode(other_var->mode())) {
1128 : DCHECK(!current->is_catch_scope());
1129 : return decl;
1130 : }
1131 : current = current->outer_scope();
1132 : } while (current != end);
1133 : }
1134 : return nullptr;
1135 : }
1136 :
1137 87363 : const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope,
1138 : VariableMode mode_limit) {
1139 : const VariableMap& variables = scope->variables_;
1140 573819 : for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr;
1141 : p = variables.Next(p)) {
1142 399414 : const AstRawString* name = static_cast<const AstRawString*>(p->key);
1143 1491 : Variable* var = LookupLocal(name);
1144 400908 : if (var != nullptr && var->mode() <= mode_limit) return name;
1145 : }
1146 : return nullptr;
1147 : }
1148 :
1149 778424 : void DeclarationScope::DeserializeReceiver(AstValueFactory* ast_value_factory) {
1150 778424 : if (is_script_scope()) {
1151 : DCHECK_NOT_NULL(receiver_);
1152 778424 : return;
1153 : }
1154 : DCHECK(has_this_declaration());
1155 638247 : DeclareThis(ast_value_factory);
1156 638247 : if (is_debug_evaluate_scope()) {
1157 12169 : receiver_->AllocateTo(VariableLocation::LOOKUP, -1);
1158 : } else {
1159 : receiver_->AllocateTo(VariableLocation::CONTEXT,
1160 1252156 : scope_info_->ReceiverContextSlotIndex());
1161 : }
1162 : }
1163 :
1164 1793949 : bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1165 : // Module variables must be allocated before variable resolution
1166 : // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1167 1793949 : if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1168 :
1169 1793949 : if (!ResolveVariablesRecursively(info)) {
1170 : DCHECK(info->pending_error_handler()->has_pending_error());
1171 : return false;
1172 : }
1173 :
1174 : // // Don't allocate variables of preparsed scopes.
1175 1793775 : if (!was_lazily_parsed()) AllocateVariablesRecursively();
1176 :
1177 : return true;
1178 : }
1179 :
1180 4183 : bool Scope::HasThisReference() const {
1181 7610 : if (is_declaration_scope() && AsDeclarationScope()->has_this_reference()) {
1182 : return true;
1183 : }
1184 :
1185 4932 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1186 4426 : if (!scope->is_declaration_scope() ||
1187 : !scope->AsDeclarationScope()->has_this_declaration()) {
1188 2368 : if (scope->HasThisReference()) return true;
1189 : }
1190 : }
1191 :
1192 : return false;
1193 : }
1194 :
1195 4113353 : bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1196 : const Scope* outer) const {
1197 : // If none of the outer scopes need to decide whether to context allocate
1198 : // specific variables, we can preparse inner functions without unresolved
1199 : // variables. Otherwise we need to find unresolved variables to force context
1200 : // allocation of the matching declarations. We can stop at the outer scope for
1201 : // the parse, since context allocation of those variables is already
1202 : // guaranteed to be correct.
1203 4113482 : for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1204 : // Eval forces context allocation on all outer scopes, so we don't need to
1205 : // look at those scopes. Sloppy eval makes top-level non-lexical variables
1206 : // dynamic, whereas strict-mode requires context allocation.
1207 3086477 : if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1208 : // Catch scopes force context allocation of all variables.
1209 2075405 : if (s->is_catch_scope()) continue;
1210 : // With scopes do not introduce variables that need allocation.
1211 2075413 : if (s->is_with_scope()) continue;
1212 : DCHECK(s->is_module_scope() || s->is_block_scope() ||
1213 : s->is_function_scope());
1214 : return false;
1215 : }
1216 : return true;
1217 : }
1218 :
1219 7152304 : bool DeclarationScope::AllowsLazyCompilation() const {
1220 : // Functions which force eager compilation and class member initializer
1221 : // functions are not lazily compilable.
1222 7152304 : return !force_eager_compilation_ &&
1223 3576899 : !IsClassMembersInitializerFunction(function_kind());
1224 : }
1225 :
1226 2699139 : int Scope::ContextChainLength(Scope* scope) const {
1227 : int n = 0;
1228 3405932 : for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1229 : DCHECK_NOT_NULL(s); // scope must be in the scope chain
1230 706793 : if (s->NeedsContext()) n++;
1231 : }
1232 2699139 : return n;
1233 : }
1234 :
1235 354324 : int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1236 : int result = 0;
1237 : int length = 0;
1238 :
1239 1446674 : for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1240 1092350 : if (!s->NeedsContext()) continue;
1241 793818 : length++;
1242 1572851 : if (s->is_declaration_scope() &&
1243 : s->AsDeclarationScope()->calls_sloppy_eval()) {
1244 : result = length;
1245 : }
1246 : }
1247 :
1248 354324 : return result;
1249 : }
1250 :
1251 17290071 : DeclarationScope* Scope::GetDeclarationScope() {
1252 5305022 : Scope* scope = this;
1253 41946155 : while (!scope->is_declaration_scope()) {
1254 : scope = scope->outer_scope();
1255 : }
1256 17290071 : return scope->AsDeclarationScope();
1257 : }
1258 :
1259 0 : const DeclarationScope* Scope::GetClosureScope() const {
1260 0 : const Scope* scope = this;
1261 0 : while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1262 : scope = scope->outer_scope();
1263 : }
1264 0 : return scope->AsDeclarationScope();
1265 : }
1266 :
1267 9319250 : DeclarationScope* Scope::GetClosureScope() {
1268 19640220 : Scope* scope = this;
1269 43276146 : while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1270 : scope = scope->outer_scope();
1271 : }
1272 9319250 : return scope->AsDeclarationScope();
1273 : }
1274 :
1275 2384967 : bool Scope::NeedsScopeInfo() const {
1276 : DCHECK(!already_resolved_);
1277 : DCHECK(GetClosureScope()->ShouldEagerCompile());
1278 : // The debugger expects all functions to have scope infos.
1279 : // TODO(jochen|yangguo): Remove this requirement.
1280 2384967 : if (is_function_scope()) return true;
1281 0 : return NeedsContext();
1282 : }
1283 :
1284 43358 : bool Scope::ShouldBanArguments() {
1285 43358 : return GetReceiverScope()->should_ban_arguments();
1286 : }
1287 :
1288 8789244 : DeclarationScope* Scope::GetReceiverScope() {
1289 9393770 : Scope* scope = this;
1290 36172451 : while (!scope->is_declaration_scope() ||
1291 8882146 : (!scope->is_script_scope() &&
1292 : !scope->AsDeclarationScope()->has_this_declaration())) {
1293 : scope = scope->outer_scope();
1294 : }
1295 8789244 : return scope->AsDeclarationScope();
1296 : }
1297 :
1298 2577042 : Scope* Scope::GetOuterScopeWithContext() {
1299 3495217 : Scope* scope = outer_scope_;
1300 9177822 : while (scope && !scope->NeedsContext()) {
1301 : scope = scope->outer_scope();
1302 : }
1303 2577042 : return scope;
1304 : }
1305 :
1306 : namespace {
1307 : bool WasLazilyParsed(Scope* scope) {
1308 21463088 : return scope->is_declaration_scope() &&
1309 : scope->AsDeclarationScope()->was_lazily_parsed();
1310 : }
1311 :
1312 : } // namespace
1313 :
1314 : template <typename FunctionType>
1315 : void Scope::ForEach(FunctionType callback) {
1316 : Scope* scope = this;
1317 : while (true) {
1318 11814049 : Iteration iteration = callback(scope);
1319 : // Try to descend into inner scopes first.
1320 11814197 : if ((iteration == Iteration::kDescend) && scope->inner_scope_ != nullptr) {
1321 : scope = scope->inner_scope_;
1322 : } else {
1323 : // Find the next outer scope with a sibling.
1324 11814096 : while (scope->sibling_ == nullptr) {
1325 5118363 : if (scope == this) return;
1326 2943815 : scope = scope->outer_scope_;
1327 : }
1328 6695733 : if (scope == this) return;
1329 : scope = scope->sibling_;
1330 : }
1331 : }
1332 : }
1333 :
1334 12376 : void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1335 : Isolate* isolate, ParseInfo* info,
1336 : Handle<StringSet>* non_locals) {
1337 17604 : this->ForEach([max_outer_scope, isolate, info, non_locals](Scope* scope) {
1338 : // Module variables must be allocated before variable resolution
1339 : // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1340 16855 : if (scope->is_module_scope()) {
1341 228 : scope->AsModuleScope()->AllocateModuleVariables();
1342 : }
1343 :
1344 : // Lazy parsed declaration scopes are already partially analyzed. If there
1345 : // are unresolved references remaining, they just need to be resolved in
1346 : // outer scopes.
1347 16855 : Scope* lookup = WasLazilyParsed(scope) ? scope->outer_scope() : scope;
1348 :
1349 91070 : for (VariableProxy* proxy : scope->unresolved_list_) {
1350 : DCHECK(!proxy->is_resolved());
1351 : Variable* var =
1352 57360 : Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1353 57360 : if (var == nullptr) {
1354 16229 : *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1355 : } else {
1356 : // In this case we need to leave scopes in a way that they can be
1357 : // allocated. If we resolved variables from lazy parsed scopes, we need
1358 : // to context allocate the var.
1359 : scope->ResolveTo(info, proxy, var);
1360 41131 : if (!var->is_dynamic() && lookup != scope)
1361 : var->ForceContextAllocation();
1362 : }
1363 : }
1364 :
1365 : // Clear unresolved_list_ as it's in an inconsistent state.
1366 : scope->unresolved_list_.Clear();
1367 16855 : return Iteration::kDescend;
1368 : });
1369 12376 : }
1370 :
1371 1858868 : void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1372 : AstNodeFactory* ast_node_factory,
1373 : UnresolvedList* new_unresolved_list) {
1374 : this->ForEach([max_outer_scope, ast_node_factory,
1375 3097729 : new_unresolved_list](Scope* scope) {
1376 : DCHECK_IMPLIES(scope->is_declaration_scope(),
1377 : !scope->AsDeclarationScope()->was_lazily_parsed());
1378 :
1379 41094247 : for (VariableProxy* proxy = scope->unresolved_list_.first();
1380 : proxy != nullptr; proxy = proxy->next_unresolved()) {
1381 : DCHECK(!proxy->is_resolved());
1382 : Variable* var =
1383 29007092 : Lookup<kParsedScope>(proxy, scope, max_outer_scope->outer_scope());
1384 22334386 : if (var == nullptr) {
1385 : // Don't copy unresolved references to the script scope, unless it's a
1386 : // reference to a private name or method. In that case keep it so we
1387 : // can fail later.
1388 13516488 : if (!max_outer_scope->outer_scope()->is_script_scope() ||
1389 171567 : proxy->IsPrivateName()) {
1390 6503327 : VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1391 6503441 : new_unresolved_list->Add(copy);
1392 : }
1393 : } else {
1394 : var->set_is_used();
1395 15661933 : if (proxy->is_assigned()) var->set_maybe_assigned();
1396 : }
1397 : }
1398 :
1399 : // Clear unresolved_list_ as it's in an inconsistent state.
1400 : scope->unresolved_list_.Clear();
1401 3097675 : return Iteration::kDescend;
1402 : });
1403 1858910 : }
1404 :
1405 12376 : Handle<StringSet> DeclarationScope::CollectNonLocals(
1406 : Isolate* isolate, ParseInfo* info, Handle<StringSet> non_locals) {
1407 12376 : Scope::CollectNonLocals(this, isolate, info, &non_locals);
1408 12376 : return non_locals;
1409 : }
1410 :
1411 2607355 : void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1412 : bool aborted) {
1413 : DCHECK(is_function_scope());
1414 :
1415 : // Reset all non-trivial members.
1416 : params_.Clear();
1417 : decls_.Clear();
1418 : locals_.Clear();
1419 2559260 : inner_scope_ = nullptr;
1420 : unresolved_list_.Clear();
1421 : sloppy_block_functions_.Clear();
1422 2559260 : rare_data_ = nullptr;
1423 2559260 : has_rest_ = false;
1424 :
1425 : DCHECK_NE(zone_, ast_value_factory->zone());
1426 2559260 : zone_->ReleaseMemory();
1427 :
1428 2559642 : if (aborted) {
1429 : // Prepare scope for use in the outer zone.
1430 48095 : zone_ = ast_value_factory->zone();
1431 48095 : variables_.Reset(ZoneAllocationPolicy(zone_));
1432 96190 : if (!IsArrowFunction(function_kind_)) {
1433 42418 : has_simple_parameters_ = true;
1434 42418 : DeclareDefaultFunctionVariables(ast_value_factory);
1435 : }
1436 : } else {
1437 : // Make sure this scope isn't used for allocation anymore.
1438 2511547 : zone_ = nullptr;
1439 : variables_.Invalidate();
1440 : }
1441 :
1442 : #ifdef DEBUG
1443 : needs_migration_ = false;
1444 : is_being_lazily_parsed_ = false;
1445 : #endif
1446 :
1447 2559642 : was_lazily_parsed_ = !aborted;
1448 2559642 : }
1449 :
1450 3375835 : bool Scope::IsSkippableFunctionScope() {
1451 : // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
1452 : // those Scopes which have their own PreparseDataBuilder object. This
1453 : // logic ensures that the scope allocation data is consistent with the
1454 : // skippable function data (both agree on where the lazy function boundaries
1455 : // are).
1456 3375835 : if (!is_function_scope()) return false;
1457 2159098 : DeclarationScope* declaration_scope = AsDeclarationScope();
1458 4881720 : return !declaration_scope->is_arrow_scope() &&
1459 227073 : declaration_scope->preparse_data_builder() != nullptr;
1460 : }
1461 :
1462 1858737 : void Scope::SavePreparseData(Parser* parser) {
1463 3097361 : this->ForEach([parser](Scope* scope) {
1464 3097361 : if (scope->IsSkippableFunctionScope()) {
1465 2000633 : scope->AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
1466 : }
1467 3097298 : return Iteration::kDescend;
1468 : });
1469 1858832 : }
1470 :
1471 0 : void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
1472 2000633 : if (preparse_data_builder_ == nullptr) return;
1473 2000648 : preparse_data_builder_->SaveScopeAllocationData(this, parser);
1474 : }
1475 :
1476 2450736 : void DeclarationScope::AnalyzePartially(Parser* parser,
1477 3294875 : AstNodeFactory* ast_node_factory) {
1478 : DCHECK(!force_eager_compilation_);
1479 : UnresolvedList new_unresolved_list;
1480 9778791 : if (!IsArrowFunction(function_kind_) &&
1481 3055222 : (!outer_scope_->is_script_scope() ||
1482 1257039 : (preparse_data_builder_ != nullptr &&
1483 628576 : preparse_data_builder_->HasInnerFunctions()))) {
1484 : // Try to resolve unresolved variables for this Scope and migrate those
1485 : // which cannot be resolved inside. It doesn't make sense to try to resolve
1486 : // them in the outer Scopes here, because they are incomplete.
1487 1858945 : Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list);
1488 :
1489 : // Migrate function_ to the right Zone.
1490 1858912 : if (function_ != nullptr) {
1491 844226 : function_ = ast_node_factory->CopyVariable(function_);
1492 : }
1493 :
1494 1858868 : SavePreparseData(parser);
1495 : }
1496 :
1497 : #ifdef DEBUG
1498 : if (FLAG_print_scopes) {
1499 : PrintF("Inner function scope:\n");
1500 : Print();
1501 : }
1502 : #endif
1503 :
1504 2450605 : ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1505 :
1506 : unresolved_list_ = std::move(new_unresolved_list);
1507 2451158 : }
1508 :
1509 : #ifdef DEBUG
1510 : namespace {
1511 :
1512 : const char* Header(ScopeType scope_type, FunctionKind function_kind,
1513 : bool is_declaration_scope) {
1514 : switch (scope_type) {
1515 : case EVAL_SCOPE: return "eval";
1516 : // TODO(adamk): Should we print concise method scopes specially?
1517 : case FUNCTION_SCOPE:
1518 : if (IsGeneratorFunction(function_kind)) return "function*";
1519 : if (IsAsyncFunction(function_kind)) return "async function";
1520 : if (IsArrowFunction(function_kind)) return "arrow";
1521 : return "function";
1522 : case MODULE_SCOPE: return "module";
1523 : case SCRIPT_SCOPE: return "global";
1524 : case CATCH_SCOPE: return "catch";
1525 : case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1526 : case WITH_SCOPE: return "with";
1527 : }
1528 : UNREACHABLE();
1529 : }
1530 :
1531 : void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1532 :
1533 : void PrintName(const AstRawString* name) {
1534 : PrintF("%.*s", name->length(), name->raw_data());
1535 : }
1536 :
1537 : void PrintLocation(Variable* var) {
1538 : switch (var->location()) {
1539 : case VariableLocation::UNALLOCATED:
1540 : break;
1541 : case VariableLocation::PARAMETER:
1542 : PrintF("parameter[%d]", var->index());
1543 : break;
1544 : case VariableLocation::LOCAL:
1545 : PrintF("local[%d]", var->index());
1546 : break;
1547 : case VariableLocation::CONTEXT:
1548 : PrintF("context[%d]", var->index());
1549 : break;
1550 : case VariableLocation::LOOKUP:
1551 : PrintF("lookup");
1552 : break;
1553 : case VariableLocation::MODULE:
1554 : PrintF("module");
1555 : break;
1556 : }
1557 : }
1558 :
1559 : void PrintVar(int indent, Variable* var) {
1560 : Indent(indent, VariableMode2String(var->mode()));
1561 : PrintF(" ");
1562 : if (var->raw_name()->IsEmpty())
1563 : PrintF(".%p", reinterpret_cast<void*>(var));
1564 : else
1565 : PrintName(var->raw_name());
1566 : PrintF("; // (%p) ", reinterpret_cast<void*>(var));
1567 : PrintLocation(var);
1568 : bool comma = !var->IsUnallocated();
1569 : if (var->has_forced_context_allocation()) {
1570 : if (comma) PrintF(", ");
1571 : PrintF("forced context allocation");
1572 : comma = true;
1573 : }
1574 : if (var->maybe_assigned() == kNotAssigned) {
1575 : if (comma) PrintF(", ");
1576 : PrintF("never assigned");
1577 : comma = true;
1578 : }
1579 : if (var->initialization_flag() == kNeedsInitialization &&
1580 : !var->binding_needs_init()) {
1581 : if (comma) PrintF(", ");
1582 : PrintF("hole initialization elided");
1583 : }
1584 : PrintF("\n");
1585 : }
1586 :
1587 : void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1588 : Variable* function_var) {
1589 : bool printed_label = false;
1590 : for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1591 : Variable* var = reinterpret_cast<Variable*>(p->value);
1592 : if (var == function_var) continue;
1593 : bool local = !IsDynamicVariableMode(var->mode());
1594 : if ((locals ? local : !local) &&
1595 : (var->is_used() || !var->IsUnallocated())) {
1596 : if (!printed_label) {
1597 : Indent(indent, label);
1598 : printed_label = true;
1599 : }
1600 : PrintVar(indent, var);
1601 : }
1602 : }
1603 : }
1604 :
1605 : } // anonymous namespace
1606 :
1607 : void DeclarationScope::PrintParameters() {
1608 : PrintF(" (");
1609 : for (int i = 0; i < params_.length(); i++) {
1610 : if (i > 0) PrintF(", ");
1611 : const AstRawString* name = params_[i]->raw_name();
1612 : if (name->IsEmpty()) {
1613 : PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1614 : } else {
1615 : PrintName(name);
1616 : }
1617 : }
1618 : PrintF(")");
1619 : }
1620 :
1621 : void Scope::Print(int n) {
1622 : int n0 = (n > 0 ? n : 0);
1623 : int n1 = n0 + 2; // indentation
1624 :
1625 : // Print header.
1626 : FunctionKind function_kind = is_function_scope()
1627 : ? AsDeclarationScope()->function_kind()
1628 : : kNormalFunction;
1629 : Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1630 : if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1631 : PrintF(" ");
1632 : PrintName(scope_name_);
1633 : }
1634 :
1635 : // Print parameters, if any.
1636 : Variable* function = nullptr;
1637 : if (is_function_scope()) {
1638 : AsDeclarationScope()->PrintParameters();
1639 : function = AsDeclarationScope()->function_var();
1640 : }
1641 :
1642 : PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
1643 : start_position(), end_position());
1644 : if (is_hidden()) {
1645 : Indent(n1, "// is hidden\n");
1646 : }
1647 :
1648 : // Function name, if any (named function literals, only).
1649 : if (function != nullptr) {
1650 : Indent(n1, "// (local) function name: ");
1651 : PrintName(function->raw_name());
1652 : PrintF("\n");
1653 : }
1654 :
1655 : // Scope info.
1656 : if (is_strict(language_mode())) {
1657 : Indent(n1, "// strict mode scope\n");
1658 : }
1659 : if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1660 : if (is_declaration_scope() && AsDeclarationScope()->calls_sloppy_eval()) {
1661 : Indent(n1, "// scope calls sloppy 'eval'\n");
1662 : }
1663 : if (is_declaration_scope() && AsDeclarationScope()->NeedsHomeObject()) {
1664 : Indent(n1, "// scope needs home object\n");
1665 : }
1666 : if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1667 : if (is_declaration_scope()) {
1668 : DeclarationScope* scope = AsDeclarationScope();
1669 : if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1670 : if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1671 : }
1672 : if (num_stack_slots_ > 0) {
1673 : Indent(n1, "// ");
1674 : PrintF("%d stack slots\n", num_stack_slots_);
1675 : }
1676 : if (num_heap_slots_ > 0) {
1677 : Indent(n1, "// ");
1678 : PrintF("%d heap slots\n", num_heap_slots_);
1679 : }
1680 :
1681 : // Print locals.
1682 : if (function != nullptr) {
1683 : Indent(n1, "// function var:\n");
1684 : PrintVar(n1, function);
1685 : }
1686 :
1687 : // Print temporaries.
1688 : {
1689 : bool printed_header = false;
1690 : for (Variable* local : locals_) {
1691 : if (local->mode() != VariableMode::kTemporary) continue;
1692 : if (!printed_header) {
1693 : printed_header = true;
1694 : Indent(n1, "// temporary vars:\n");
1695 : }
1696 : PrintVar(n1, local);
1697 : }
1698 : }
1699 :
1700 : if (variables_.occupancy() > 0) {
1701 : PrintMap(n1, "// local vars:\n", &variables_, true, function);
1702 : PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1703 : }
1704 :
1705 : // Print inner scopes (disable by providing negative n).
1706 : if (n >= 0) {
1707 : for (Scope* scope = inner_scope_; scope != nullptr;
1708 : scope = scope->sibling_) {
1709 : PrintF("\n");
1710 : scope->Print(n1);
1711 : }
1712 : }
1713 :
1714 : Indent(n0, "}\n");
1715 : }
1716 :
1717 : void Scope::CheckScopePositions() {
1718 : this->ForEach([](Scope* scope) {
1719 : // Visible leaf scopes must have real positions.
1720 : if (!scope->is_hidden() && scope->inner_scope_ == nullptr) {
1721 : DCHECK_NE(kNoSourcePosition, scope->start_position());
1722 : DCHECK_NE(kNoSourcePosition, scope->end_position());
1723 : }
1724 : return Iteration::kDescend;
1725 : });
1726 : }
1727 :
1728 : void Scope::CheckZones() {
1729 : DCHECK(!needs_migration_);
1730 : this->ForEach([](Scope* scope) {
1731 : if (WasLazilyParsed(scope)) {
1732 : DCHECK_NULL(scope->zone());
1733 : DCHECK_NULL(scope->inner_scope_);
1734 : return Iteration::kContinue;
1735 : }
1736 : return Iteration::kDescend;
1737 : });
1738 : }
1739 : #endif // DEBUG
1740 :
1741 725622 : Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
1742 : // Declare a new non-local.
1743 : DCHECK(IsDynamicVariableMode(mode));
1744 : bool was_added;
1745 : Variable* var =
1746 : variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
1747 725622 : kCreatedInitialized, kNotAssigned, &was_added);
1748 : // Allocate it by giving it a dynamic lookup.
1749 : var->AllocateTo(VariableLocation::LOOKUP, -1);
1750 725618 : return var;
1751 : }
1752 :
1753 : // static
1754 : template <Scope::ScopeLookupMode mode>
1755 43910408 : Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
1756 : Scope* outer_scope_end, Scope* entry_point,
1757 : bool force_context_allocation) {
1758 : if (mode == kDeserializedScope) {
1759 2068071 : Variable* var = entry_point->variables_.Lookup(proxy->raw_name());
1760 2068072 : if (var != nullptr) return var;
1761 : }
1762 :
1763 : while (true) {
1764 : DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
1765 : // Short-cut: whenever we find a debug-evaluate scope, just look everything
1766 : // up dynamically. Debug-evaluate doesn't properly create scope info for the
1767 : // lookups it does. It may not have a valid 'this' declaration, and anything
1768 : // accessed through debug-evaluate might invalidly resolve to
1769 : // stack-allocated variables.
1770 : // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
1771 : // the scopes in which it's evaluating.
1772 2180751 : if (mode == kDeserializedScope &&
1773 2180751 : V8_UNLIKELY(scope->is_debug_evaluate_scope_)) {
1774 10672 : return entry_point->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1775 : }
1776 :
1777 : // Try to find the variable in this scope.
1778 : Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
1779 : : scope->LookupInScopeInfo(
1780 2170079 : proxy->raw_name(), entry_point);
1781 :
1782 : // We found a variable and we are done. (Even if there is an 'eval' in this
1783 : // scope which introduces the same variable again, the resulting variable
1784 : // remains the same.)
1785 60132591 : if (var != nullptr) {
1786 38728764 : if (mode == kParsedScope && force_context_allocation &&
1787 : !var->is_dynamic()) {
1788 : var->ForceContextAllocation();
1789 : }
1790 31511643 : return var;
1791 : }
1792 :
1793 28172797 : if (scope->outer_scope_ == outer_scope_end) break;
1794 :
1795 : DCHECK(!scope->is_script_scope());
1796 19519986 : if (V8_UNLIKELY(scope->is_with_scope())) {
1797 : return LookupWith(proxy, scope, outer_scope_end, entry_point,
1798 46205 : force_context_allocation);
1799 : }
1800 34963351 : if (V8_UNLIKELY(scope->is_declaration_scope() &&
1801 : scope->AsDeclarationScope()->calls_sloppy_eval())) {
1802 : return LookupSloppyEval(proxy, scope, outer_scope_end, entry_point,
1803 385962 : force_context_allocation);
1804 : }
1805 :
1806 19087819 : force_context_allocation |= scope->is_function_scope();
1807 : scope = scope->outer_scope_;
1808 : // TODO(verwaest): Separate through AnalyzePartially.
1809 18619374 : if (mode == kParsedScope && !scope->scope_info_.is_null()) {
1810 1748881 : return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, scope);
1811 : }
1812 : }
1813 :
1814 : // We may just be trying to find all free variables. In that case, don't
1815 : // declare them in the outer scope.
1816 : // TODO(marja): Separate Lookup for preparsed scopes better.
1817 7690495 : if (mode == kParsedScope && !scope->is_script_scope()) {
1818 : return nullptr;
1819 : }
1820 1961868 : if (V8_UNLIKELY(proxy->IsPrivateName())) return nullptr;
1821 :
1822 : // No binding has been found. Declare a variable on the global object.
1823 : return scope->AsDeclarationScope()->DeclareDynamicGlobal(
1824 : proxy->raw_name(), NORMAL_VARIABLE,
1825 2430179 : mode == kDeserializedScope ? entry_point : scope);
1826 : }
1827 :
1828 : template Variable* Scope::Lookup<Scope::kParsedScope>(
1829 : VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1830 : Scope* entry_point, bool force_context_allocation);
1831 : template Variable* Scope::Lookup<Scope::kDeserializedScope>(
1832 : VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
1833 : Scope* entry_point, bool force_context_allocation);
1834 :
1835 58053 : Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
1836 : Scope* outer_scope_end, Scope* entry_point,
1837 : bool force_context_allocation) {
1838 : DCHECK(scope->is_with_scope());
1839 :
1840 : Variable* var =
1841 46204 : scope->outer_scope_->scope_info_.is_null()
1842 : ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1843 44573 : nullptr, force_context_allocation)
1844 : : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1845 90777 : outer_scope_end, entry_point);
1846 :
1847 46204 : if (var == nullptr) return var;
1848 :
1849 : // The current scope is a with scope, so the variable binding can not be
1850 : // statically resolved. However, note that it was necessary to do a lookup
1851 : // in the outer scope anyway, because if a binding exists in an outer
1852 : // scope, the associated variable has to be marked as potentially being
1853 : // accessed from inside of an inner with scope (the property may not be in
1854 : // the 'with' object).
1855 41052 : if (!var->is_dynamic() && var->IsUnallocated()) {
1856 : DCHECK(!scope->already_resolved_);
1857 : var->set_is_used();
1858 : var->ForceContextAllocation();
1859 11849 : if (proxy->is_assigned()) var->set_maybe_assigned();
1860 : }
1861 28958 : if (entry_point != nullptr) entry_point->variables_.Remove(var);
1862 28958 : Scope* target = entry_point == nullptr ? scope : entry_point;
1863 28958 : return target->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
1864 : }
1865 :
1866 385962 : Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
1867 : Scope* outer_scope_end, Scope* entry_point,
1868 : bool force_context_allocation) {
1869 : DCHECK(scope->is_declaration_scope() &&
1870 : scope->AsDeclarationScope()->calls_sloppy_eval());
1871 :
1872 : // If we're compiling eval, it's possible that the outer scope is the first
1873 : // ScopeInfo-backed scope.
1874 385962 : Scope* entry = entry_point == nullptr ? scope->outer_scope_ : entry_point;
1875 : Variable* var =
1876 385962 : scope->outer_scope_->scope_info_.is_null()
1877 : ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
1878 68401 : nullptr, force_context_allocation)
1879 : : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
1880 454363 : outer_scope_end, entry);
1881 385962 : if (var == nullptr) return var;
1882 :
1883 : // A variable binding may have been found in an outer scope, but the current
1884 : // scope makes a sloppy 'eval' call, so the found variable may not be the
1885 : // correct one (the 'eval' may introduce a binding with the same name). In
1886 : // that case, change the lookup result to reflect this situation. Only
1887 : // scopes that can host var bindings (declaration scopes) need be considered
1888 : // here (this excludes block and catch scopes), and variable lookups at
1889 : // script scope are always dynamic.
1890 379614 : if (var->IsGlobalObjectProperty()) {
1891 373237 : Scope* target = entry_point == nullptr ? scope : entry_point;
1892 373237 : return target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
1893 : }
1894 :
1895 6377 : if (var->is_dynamic()) return var;
1896 :
1897 : Variable* invalidated = var;
1898 4426 : if (entry_point != nullptr) entry_point->variables_.Remove(invalidated);
1899 :
1900 4426 : Scope* target = entry_point == nullptr ? scope : entry_point;
1901 4426 : var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
1902 : var->set_local_if_not_shadowed(invalidated);
1903 :
1904 4426 : return var;
1905 : }
1906 :
1907 18585288 : bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
1908 : DCHECK(info->script_scope()->is_script_scope());
1909 : DCHECK(!proxy->is_resolved());
1910 18585288 : Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
1911 18585308 : if (var == nullptr) {
1912 : DCHECK(proxy->IsPrivateName());
1913 : info->pending_error_handler()->ReportMessageAt(
1914 133 : proxy->position(), proxy->position() + 1,
1915 : MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
1916 133 : kSyntaxError);
1917 133 : return false;
1918 : }
1919 : ResolveTo(info, proxy, var);
1920 18585194 : return true;
1921 : }
1922 :
1923 : namespace {
1924 :
1925 : void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
1926 : proxy->set_needs_hole_check();
1927 : var->ForceHoleInitialization();
1928 : }
1929 :
1930 20993282 : void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
1931 18630121 : if (var->mode() == VariableMode::kDynamicLocal) {
1932 : // Dynamically introduced variables never need a hole check (since they're
1933 : // VariableMode::kVar bindings, either from var or function declarations),
1934 : // but the variable they shadow might need a hole check, which we want to do
1935 : // if we decide that no shadowing variable was dynamically introoduced.
1936 : DCHECK_EQ(kCreatedInitialized, var->initialization_flag());
1937 3761 : return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
1938 : }
1939 :
1940 18626360 : if (var->initialization_flag() == kCreatedInitialized) return;
1941 :
1942 : // It's impossible to eliminate module import hole checks here, because it's
1943 : // unknown at compilation time whether the binding referred to in the
1944 : // exporting module itself requires hole checks.
1945 1478756 : if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
1946 : return SetNeedsHoleCheck(var, proxy);
1947 : }
1948 :
1949 : // Check if the binding really needs an initialization check. The check
1950 : // can be skipped in the following situation: we have a VariableMode::kLet or
1951 : // VariableMode::kConst binding, both the Variable and the VariableProxy have
1952 : // the same declaration scope (i.e. they are both in global code, in the same
1953 : // function or in the same eval code), the VariableProxy is in the source
1954 : // physically located after the initializer of the variable, and that the
1955 : // initializer cannot be skipped due to a nonlinear scope.
1956 : //
1957 : // The condition on the closure scopes is a conservative check for
1958 : // nested functions that access a binding and are called before the
1959 : // binding is initialized:
1960 : // function() { f(); let x = 1; function f() { x = 2; } }
1961 : //
1962 : // The check cannot be skipped on non-linear scopes, namely switch
1963 : // scopes, to ensure tests are done in cases like the following:
1964 : // switch (1) { case 0: let x = 2; case 1: f(x); }
1965 : // The scope of the variable needs to be checked, in case the use is
1966 : // in a sub-block which may be linear.
1967 1475360 : if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
1968 : return SetNeedsHoleCheck(var, proxy);
1969 : }
1970 :
1971 : // We should always have valid source positions.
1972 : DCHECK_NE(var->initializer_position(), kNoSourcePosition);
1973 : DCHECK_NE(proxy->position(), kNoSourcePosition);
1974 :
1975 1775713 : if (var->scope()->is_nonlinear() ||
1976 887801 : var->initializer_position() >= proxy->position()) {
1977 : return SetNeedsHoleCheck(var, proxy);
1978 : }
1979 : }
1980 :
1981 : } // anonymous namespace
1982 :
1983 0 : void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
1984 : #ifdef DEBUG
1985 : if (info->is_native()) {
1986 : // To avoid polluting the global object in native scripts
1987 : // - Variables must not be allocated to the global scope.
1988 : DCHECK_NOT_NULL(outer_scope());
1989 : // - Variables must be bound locally or unallocated.
1990 : if (var->IsGlobalObjectProperty()) {
1991 : // The following variable name may be minified. If so, disable
1992 : // minification in js2c.py for better output.
1993 : Handle<String> name = proxy->raw_name()->string();
1994 : FATAL("Unbound variable: '%s' in native script.",
1995 : name->ToCString().get());
1996 : }
1997 : VariableLocation location = var->location();
1998 : DCHECK(location == VariableLocation::LOCAL ||
1999 : location == VariableLocation::CONTEXT ||
2000 : location == VariableLocation::PARAMETER ||
2001 : location == VariableLocation::UNALLOCATED);
2002 : }
2003 : #endif
2004 :
2005 : DCHECK_NOT_NULL(var);
2006 18626306 : UpdateNeedsHoleCheck(var, proxy, this);
2007 18626485 : proxy->BindTo(var);
2008 0 : }
2009 :
2010 8726545 : bool Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
2011 : Scope* end) {
2012 : // Resolve the variable in all parsed scopes to force context allocation.
2013 10788059 : for (; scope != end; scope = scope->outer_scope_) {
2014 : Variable* var = scope->LookupLocal(proxy->raw_name());
2015 6517317 : if (var != nullptr) {
2016 : var->set_is_used();
2017 2228726 : if (!var->is_dynamic()) {
2018 : var->ForceContextAllocation();
2019 2227031 : if (proxy->is_assigned()) var->set_maybe_assigned();
2020 : }
2021 : return true;
2022 : }
2023 : }
2024 :
2025 4271781 : if (!proxy->IsPrivateName()) return true;
2026 :
2027 : // If we're resolving a private name, throw an exception of we didn't manage
2028 : // to resolve. In case of eval, also look in all outer scope-info backed
2029 : // scopes except for the script scope. Don't throw an exception if a reference
2030 : // was found.
2031 : Scope* start = scope;
2032 46 : for (; !scope->is_script_scope(); scope = scope->outer_scope_) {
2033 0 : if (scope->LookupInScopeInfo(proxy->raw_name(), start) != nullptr) {
2034 : return true;
2035 : }
2036 : }
2037 :
2038 : return false;
2039 : }
2040 :
2041 12101800 : bool Scope::ResolveVariablesRecursively(ParseInfo* info) {
2042 : DCHECK(info->script_scope()->is_script_scope());
2043 : // Lazy parsed declaration scopes are already partially analyzed. If there are
2044 : // unresolved references remaining, they just need to be resolved in outer
2045 : // scopes.
2046 5602385 : if (WasLazilyParsed(this)) {
2047 : DCHECK_EQ(variables_.occupancy(), 0);
2048 2669713 : Scope* end = info->scope();
2049 : // Resolve in all parsed scopes except for the script scope.
2050 2420521 : if (!end->is_script_scope()) end = end->outer_scope();
2051 :
2052 11340405 : for (VariableProxy* proxy : unresolved_list_) {
2053 6499415 : if (!ResolvePreparsedVariable(proxy, outer_scope(), end)) {
2054 : info->pending_error_handler()->ReportMessageAt(
2055 46 : proxy->position(), proxy->position() + 1,
2056 : MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name(),
2057 46 : kSyntaxError);
2058 : DCHECK(proxy->IsPrivateName());
2059 : return false;
2060 : }
2061 : }
2062 : } else {
2063 : // Resolve unresolved variables for this scope.
2064 24948934 : for (VariableProxy* proxy : unresolved_list_) {
2065 18585385 : if (!ResolveVariable(info, proxy)) return false;
2066 : }
2067 :
2068 : // Resolve unresolved variables for inner scopes.
2069 6989914 : for (Scope* scope = inner_scope_; scope != nullptr;
2070 : scope = scope->sibling_) {
2071 3808375 : if (!scope->ResolveVariablesRecursively(info)) return false;
2072 : }
2073 : }
2074 : return true;
2075 : }
2076 :
2077 51827126 : bool Scope::MustAllocate(Variable* var) {
2078 : DCHECK(var->location() != VariableLocation::MODULE);
2079 : // Give var a read/write use if there is a chance it might be accessed
2080 : // via an eval() call. This is only possible if the variable has a
2081 : // visible name.
2082 37631452 : if (!var->raw_name()->IsEmpty() &&
2083 15970188 : (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2084 : var->set_is_used();
2085 4060761 : if (inner_scope_calls_eval_) var->set_maybe_assigned();
2086 : }
2087 : DCHECK(!var->has_forced_context_allocation() || var->is_used());
2088 : // Global variables do not need to be allocated.
2089 35856938 : return !var->IsGlobalObjectProperty() && var->is_used();
2090 : }
2091 :
2092 :
2093 20904858 : bool Scope::MustAllocateInContext(Variable* var) {
2094 : // If var is accessed from an inner scope, or if there is a possibility
2095 : // that it might be accessed from the current or an inner scope (through
2096 : // an eval() call or a runtime with lookup), it must be allocated in the
2097 : // context.
2098 : //
2099 : // Temporary variables are always stack-allocated. Catch-bound variables are
2100 : // always context-allocated.
2101 11075517 : if (var->mode() == VariableMode::kTemporary) return false;
2102 9829341 : if (is_catch_scope()) return true;
2103 9733583 : if ((is_script_scope() || is_eval_scope()) &&
2104 : IsLexicalVariableMode(var->mode())) {
2105 : return true;
2106 : }
2107 9136333 : return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2108 : }
2109 :
2110 :
2111 6687446 : void Scope::AllocateStackSlot(Variable* var) {
2112 6687446 : if (is_block_scope()) {
2113 371434 : outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2114 : } else {
2115 6316012 : var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2116 : }
2117 6316012 : }
2118 :
2119 :
2120 : void Scope::AllocateHeapSlot(Variable* var) {
2121 2260024 : var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2122 : }
2123 :
2124 1584482 : void DeclarationScope::AllocateParameterLocals() {
2125 : DCHECK(is_function_scope());
2126 :
2127 : bool has_mapped_arguments = false;
2128 1584481 : if (arguments_ != nullptr) {
2129 : DCHECK(!is_arrow_scope());
2130 1064694 : if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2131 : // 'arguments' is used and does not refer to a function
2132 : // parameter of the same name. If the arguments object
2133 : // aliases formal parameters, we conservatively allocate
2134 : // them specially in the loop below.
2135 : has_mapped_arguments =
2136 115248 : GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2137 : } else {
2138 : // 'arguments' is unused. Tell the code generator that it does not need to
2139 : // allocate the arguments object by nulling out arguments_.
2140 949447 : arguments_ = nullptr;
2141 : }
2142 : }
2143 :
2144 : // The same parameter may occur multiple times in the parameters_ list.
2145 : // If it does, and if it is not copied into the context object, it must
2146 : // receive the highest parameter index for that parameter; thus iteration
2147 : // order is relevant!
2148 4052330 : for (int i = num_parameters() - 1; i >= 0; --i) {
2149 2467845 : Variable* var = params_[i];
2150 : DCHECK_NOT_NULL(var);
2151 : DCHECK(!has_rest_ || var != rest_parameter());
2152 : DCHECK_EQ(this, var->scope());
2153 2467848 : if (has_mapped_arguments) {
2154 18108 : var->set_is_used();
2155 18108 : var->set_maybe_assigned();
2156 18108 : var->ForceContextAllocation();
2157 : }
2158 : AllocateParameter(var, i);
2159 : }
2160 : }
2161 :
2162 : void DeclarationScope::AllocateParameter(Variable* var, int index) {
2163 3585608 : if (!MustAllocate(var)) return;
2164 5329710 : if (has_forced_context_allocation_for_parameters() ||
2165 2664852 : MustAllocateInContext(var)) {
2166 : DCHECK(var->IsUnallocated() || var->IsContextSlot());
2167 162252 : if (var->IsUnallocated()) AllocateHeapSlot(var);
2168 : } else {
2169 : DCHECK(var->IsUnallocated() || var->IsParameter());
2170 2502606 : if (var->IsUnallocated()) {
2171 2498070 : var->AllocateTo(VariableLocation::PARAMETER, index);
2172 : }
2173 : }
2174 : }
2175 :
2176 1117755 : void DeclarationScope::AllocateReceiver() {
2177 2692757 : if (!has_this_declaration()) return;
2178 : DCHECK_NOT_NULL(receiver());
2179 : DCHECK_EQ(receiver()->scope(), this);
2180 1117755 : AllocateParameter(receiver(), -1);
2181 : }
2182 :
2183 15269788 : void Scope::AllocateNonParameterLocal(Variable* var) {
2184 : DCHECK_EQ(var->scope(), this);
2185 15269788 : if (var->IsUnallocated() && MustAllocate(var)) {
2186 8408615 : if (MustAllocateInContext(var)) {
2187 : AllocateHeapSlot(var);
2188 : DCHECK_IMPLIES(is_catch_scope(),
2189 : var->index() == Context::THROWN_OBJECT_INDEX);
2190 : } else {
2191 6316015 : AllocateStackSlot(var);
2192 : }
2193 : }
2194 15269836 : }
2195 :
2196 : void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2197 18429262 : for (Variable* local : locals_) {
2198 15247694 : AllocateNonParameterLocal(local);
2199 : }
2200 :
2201 3181570 : if (is_declaration_scope()) {
2202 2692767 : AsDeclarationScope()->AllocateLocals();
2203 : }
2204 : }
2205 :
2206 2692774 : void DeclarationScope::AllocateLocals() {
2207 : // For now, function_ must be allocated at the very end. If it gets
2208 : // allocated in the context, it must be the last slot in the context,
2209 : // because of the current ScopeInfo implementation (see
2210 : // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2211 2692761 : if (function_ != nullptr && MustAllocate(function_)) {
2212 22117 : AllocateNonParameterLocal(function_);
2213 : } else {
2214 2670643 : function_ = nullptr;
2215 : }
2216 :
2217 : DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||
2218 : !rest_parameter()->IsUnallocated());
2219 :
2220 2692772 : if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2221 987629 : new_target_ = nullptr;
2222 : }
2223 :
2224 : NullifyRareVariableIf(RareVariable::kThisFunction,
2225 164450 : [=](Variable* var) { return !MustAllocate(var); });
2226 : }
2227 :
2228 18230 : void ModuleScope::AllocateModuleVariables() {
2229 19436 : for (const auto& it : module()->regular_imports()) {
2230 1206 : Variable* var = LookupLocal(it.first);
2231 1206 : var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2232 : DCHECK(!var->IsExport());
2233 : }
2234 :
2235 36950 : for (const auto& it : module()->regular_exports()) {
2236 18720 : Variable* var = LookupLocal(it.first);
2237 18720 : var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2238 : DCHECK(var->IsExport());
2239 : }
2240 9115 : }
2241 :
2242 1793772 : void Scope::AllocateVariablesRecursively() {
2243 11476446 : this->ForEach([](Scope* scope) -> Iteration {
2244 : DCHECK(!scope->already_resolved_);
2245 5602111 : if (WasLazilyParsed(scope)) return Iteration::kContinue;
2246 : DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope->num_heap_slots_);
2247 :
2248 : // Allocate variables for this scope.
2249 : // Parameters must be allocated first, if any.
2250 3181563 : if (scope->is_declaration_scope()) {
2251 2692761 : if (scope->is_function_scope()) {
2252 : scope->AsDeclarationScope()->AllocateParameterLocals();
2253 : }
2254 : scope->AsDeclarationScope()->AllocateReceiver();
2255 : }
2256 : scope->AllocateNonParameterLocalsAndDeclaredGlobals();
2257 :
2258 : // Force allocation of a context for this scope if necessary. For a 'with'
2259 : // scope and for a function scope that makes an 'eval' call we need a
2260 : // context, even if no local variables were statically allocated in the
2261 : // scope. Likewise for modules and function scopes representing asm.js
2262 : // modules. Also force a context, if the scope is stricter than the outer
2263 : // scope.
2264 : bool must_have_context =
2265 6279007 : scope->is_with_scope() || scope->is_module_scope() ||
2266 3130814 : scope->IsAsmModule() || scope->ForceContextForLanguageMode() ||
2267 1580237 : (scope->is_function_scope() &&
2268 6228133 : scope->AsDeclarationScope()->calls_sloppy_eval()) ||
2269 354443 : (scope->is_block_scope() && scope->is_declaration_scope() &&
2270 : scope->AsDeclarationScope()->calls_sloppy_eval());
2271 :
2272 : // If we didn't allocate any locals in the local context, then we only
2273 : // need the minimal number of slots if we must have a context.
2274 3181574 : if (scope->num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
2275 : !must_have_context) {
2276 2740075 : scope->num_heap_slots_ = 0;
2277 : }
2278 :
2279 : // Allocation done.
2280 : DCHECK(scope->num_heap_slots_ == 0 ||
2281 : scope->num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
2282 : return Iteration::kDescend;
2283 : });
2284 1793783 : }
2285 :
2286 2384967 : void Scope::AllocateScopeInfosRecursively(Isolate* isolate,
2287 1244675 : MaybeHandle<ScopeInfo> outer_scope) {
2288 : DCHECK(scope_info_.is_null());
2289 2384967 : MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2290 :
2291 2384967 : if (NeedsScopeInfo()) {
2292 1244675 : scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2293 : // The ScopeInfo chain should mirror the context chain, so we only link to
2294 : // the next outer scope that needs a context.
2295 1244676 : if (NeedsContext()) next_outer_scope = scope_info_;
2296 : }
2297 :
2298 : // Allocate ScopeInfos for inner scopes.
2299 5306341 : for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2300 5524606 : if (!scope->is_function_scope() ||
2301 : scope->AsDeclarationScope()->ShouldEagerCompile()) {
2302 827152 : scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2303 : }
2304 : }
2305 2384968 : }
2306 :
2307 : // static
2308 3115636 : void DeclarationScope::AllocateScopeInfos(ParseInfo* info, Isolate* isolate) {
2309 1557814 : DeclarationScope* scope = info->literal()->scope();
2310 1557814 : if (!scope->scope_info_.is_null()) return; // Allocated by outer function.
2311 :
2312 1557814 : MaybeHandle<ScopeInfo> outer_scope;
2313 1557814 : if (scope->outer_scope_ != nullptr) {
2314 1405421 : outer_scope = scope->outer_scope_->scope_info_;
2315 : }
2316 :
2317 2503957 : scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2318 :
2319 : // The debugger expects all shared function infos to contain a scope info.
2320 : // Since the top-most scope will end up in a shared function info, make sure
2321 : // it has one, even if it doesn't need a scope info.
2322 : // TODO(jochen|yangguo): Remove this requirement.
2323 1557820 : if (scope->scope_info_.is_null()) {
2324 : scope->scope_info_ =
2325 946143 : ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2326 : }
2327 :
2328 : // Ensuring that the outer script scope has a scope info avoids having
2329 : // special case for native contexts vs other contexts.
2330 3115644 : if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2331 : info->script_scope()->scope_info_ =
2332 1059935 : handle(ScopeInfo::Empty(isolate), isolate);
2333 : }
2334 : }
2335 :
2336 145 : int Scope::ContextLocalCount() const {
2337 90 : if (num_heap_slots() == 0) return 0;
2338 : Variable* function =
2339 55 : is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2340 : bool is_function_var_in_context =
2341 55 : function != nullptr && function->IsContextSlot();
2342 55 : return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
2343 55 : (is_function_var_in_context ? 1 : 0);
2344 : }
2345 :
2346 : } // namespace internal
2347 178779 : } // namespace v8
|