Bug Summary

File:out/../deps/v8/src/ast/scopes.cc
Warning:line 2217, column 5
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name scopes.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/inspector-generated-output-root -I ../deps/v8/third_party/inspector_protocol -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/v8/third_party/zlib -I ../deps/v8/third_party/zlib/google -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/ast/scopes.cc
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/ast/ast.h"
10#include "src/base/logging.h"
11#include "src/base/optional.h"
12#include "src/builtins/accessors.h"
13#include "src/common/message-template.h"
14#include "src/heap/local-factory-inl.h"
15#include "src/init/bootstrapper.h"
16#include "src/logging/runtime-call-stats-scope.h"
17#include "src/objects/module-inl.h"
18#include "src/objects/objects-inl.h"
19#include "src/objects/scope-info.h"
20#include "src/objects/string-set-inl.h"
21#include "src/parsing/parse-info.h"
22#include "src/parsing/parser.h"
23#include "src/parsing/preparse-data.h"
24#include "src/zone/zone-list-inl.h"
25#include "src/zone/zone.h"
26
27namespace v8 {
28namespace internal {
29
30// ----------------------------------------------------------------------------
31// Implementation of LocalsMap
32//
33// Note: We are storing the handle locations as key values in the hash map.
34// When inserting a new variable via Declare(), we rely on the fact that
35// the handle location remains alive for the duration of that variable
36// use. Because a Variable holding a handle with the same location exists
37// this is ensured.
38
39static_assert(sizeof(VariableMap) == (sizeof(void*) + 2 * sizeof(uint32_t) +
40 sizeof(ZoneAllocationPolicy)),
41 "Empty base optimization didn't kick in for VariableMap");
42
43VariableMap::VariableMap(Zone* zone)
44 : ZoneHashMap(8, ZoneAllocationPolicy(zone)) {}
45
46VariableMap::VariableMap(const VariableMap& other, Zone* zone)
47 : ZoneHashMap(other, ZoneAllocationPolicy(zone)) {}
48
49Variable* VariableMap::Declare(Zone* zone, Scope* scope,
50 const AstRawString* name, VariableMode mode,
51 VariableKind kind,
52 InitializationFlag initialization_flag,
53 MaybeAssignedFlag maybe_assigned_flag,
54 IsStaticFlag is_static_flag, bool* was_added) {
55 DCHECK_EQ(zone, allocator().zone())((void) 0);
56 // AstRawStrings are unambiguous, i.e., the same string is always represented
57 // by the same AstRawString*.
58 // FIXME(marja): fix the type of Lookup.
59 Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
60 name->Hash());
61 *was_added = p->value == nullptr;
62 if (*was_added) {
63 // The variable has not been declared yet -> insert it.
64 DCHECK_EQ(name, p->key)((void) 0);
65 Variable* variable =
66 zone->New<Variable>(scope, name, mode, kind, initialization_flag,
67 maybe_assigned_flag, is_static_flag);
68 p->value = variable;
69 }
70 return reinterpret_cast<Variable*>(p->value);
71}
72
73void VariableMap::Remove(Variable* var) {
74 const AstRawString* name = var->raw_name();
75 ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->Hash());
76}
77
78void VariableMap::Add(Variable* var) {
79 const AstRawString* name = var->raw_name();
80 Entry* p = ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name),
81 name->Hash());
82 DCHECK_NULL(p->value)((void) 0);
83 DCHECK_EQ(name, p->key)((void) 0);
84 p->value = var;
85}
86
87Variable* VariableMap::Lookup(const AstRawString* name) {
88 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->Hash());
89 if (p != nullptr) {
90 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name)((void) 0);
91 DCHECK_NOT_NULL(p->value)((void) 0);
92 return reinterpret_cast<Variable*>(p->value);
93 }
94 return nullptr;
95}
96
97// ----------------------------------------------------------------------------
98// Implementation of Scope
99
100Scope::Scope(Zone* zone)
101 : outer_scope_(nullptr), variables_(zone), scope_type_(SCRIPT_SCOPE) {
102 SetDefaults();
103}
104
105Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
106 : outer_scope_(outer_scope), variables_(zone), scope_type_(scope_type) {
107 DCHECK_NE(SCRIPT_SCOPE, scope_type)((void) 0);
108 SetDefaults();
109 set_language_mode(outer_scope->language_mode());
110 private_name_lookup_skips_outer_class_ =
111 outer_scope->is_class_scope() &&
112 outer_scope->AsClassScope()->IsParsingHeritage();
113 outer_scope_->AddInnerScope(this);
114}
115
116Variable* Scope::DeclareHomeObjectVariable(AstValueFactory* ast_value_factory) {
117 bool was_added;
118 Variable* home_object_variable = Declare(
119 zone(), ast_value_factory->dot_home_object_string(), VariableMode::kConst,
120 NORMAL_VARIABLE, InitializationFlag::kCreatedInitialized,
121 MaybeAssignedFlag::kNotAssigned, &was_added);
122 DCHECK(was_added)((void) 0);
123 home_object_variable->set_is_used();
124 home_object_variable->ForceContextAllocation();
125 return home_object_variable;
126}
127
128Variable* Scope::DeclareStaticHomeObjectVariable(
129 AstValueFactory* ast_value_factory) {
130 bool was_added;
131 Variable* static_home_object_variable =
132 Declare(zone(), ast_value_factory->dot_static_home_object_string(),
133 VariableMode::kConst, NORMAL_VARIABLE,
134 InitializationFlag::kCreatedInitialized,
135 MaybeAssignedFlag::kNotAssigned, &was_added);
136 DCHECK(was_added)((void) 0);
137 static_home_object_variable->set_is_used();
138 static_home_object_variable->ForceContextAllocation();
139 return static_home_object_variable;
140}
141
142DeclarationScope::DeclarationScope(Zone* zone,
143 AstValueFactory* ast_value_factory,
144 REPLMode repl_mode)
145 : Scope(zone),
146 function_kind_(repl_mode == REPLMode::kYes
147 ? FunctionKind::kAsyncFunction
148 : FunctionKind::kNormalFunction),
149 params_(4, zone) {
150 DCHECK_EQ(scope_type_, SCRIPT_SCOPE)((void) 0);
151 SetDefaults();
152 is_repl_mode_scope_ = repl_mode == REPLMode::kYes;
153 receiver_ = DeclareDynamicGlobal(ast_value_factory->this_string(),
154 THIS_VARIABLE, this);
155}
156
157DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
158 ScopeType scope_type,
159 FunctionKind function_kind)
160 : Scope(zone, outer_scope, scope_type),
161 function_kind_(function_kind),
162 params_(4, zone) {
163 DCHECK_NE(scope_type, SCRIPT_SCOPE)((void) 0);
164 SetDefaults();
165}
166
167ModuleScope::ModuleScope(DeclarationScope* script_scope,
168 AstValueFactory* avfactory)
169 : DeclarationScope(avfactory->single_parse_zone(), script_scope,
170 MODULE_SCOPE, FunctionKind::kModule),
171 module_descriptor_(
172 avfactory->single_parse_zone()->New<SourceTextModuleDescriptor>(
173 avfactory->single_parse_zone())) {
174 set_language_mode(LanguageMode::kStrict);
175 DeclareThis(avfactory);
176}
177
178ModuleScope::ModuleScope(Handle<ScopeInfo> scope_info,
179 AstValueFactory* avfactory)
180 : DeclarationScope(avfactory->single_parse_zone(), MODULE_SCOPE, avfactory,
181 scope_info),
182 module_descriptor_(nullptr) {
183 set_language_mode(LanguageMode::kStrict);
184}
185
186ClassScope::ClassScope(Zone* zone, Scope* outer_scope, bool is_anonymous)
187 : Scope(zone, outer_scope, CLASS_SCOPE),
188 rare_data_and_is_parsing_heritage_(nullptr),
189 is_anonymous_class_(is_anonymous) {
190 set_language_mode(LanguageMode::kStrict);
191}
192
193template <typename IsolateT>
194ClassScope::ClassScope(IsolateT* isolate, Zone* zone,
195 AstValueFactory* ast_value_factory,
196 Handle<ScopeInfo> scope_info)
197 : Scope(zone, CLASS_SCOPE, ast_value_factory, scope_info),
198 rare_data_and_is_parsing_heritage_(nullptr) {
199 set_language_mode(LanguageMode::kStrict);
200 if (scope_info->ClassScopeHasPrivateBrand()) {
201 Variable* brand =
202 LookupInScopeInfo(ast_value_factory->dot_brand_string(), this);
203 DCHECK_NOT_NULL(brand)((void) 0);
204 EnsureRareData()->brand = brand;
205 }
206
207 // If the class variable is context-allocated and its index is
208 // saved for deserialization, deserialize it.
209 if (scope_info->HasSavedClassVariable()) {
210 String name;
211 int index;
212 std::tie(name, index) = scope_info->SavedClassVariable();
213 DCHECK_EQ(scope_info->ContextLocalMode(index), VariableMode::kConst)((void) 0);
214 DCHECK_EQ(scope_info->ContextLocalInitFlag(index),((void) 0)
215 InitializationFlag::kNeedsInitialization)((void) 0);
216 DCHECK_EQ(scope_info->ContextLocalMaybeAssignedFlag(index),((void) 0)
217 MaybeAssignedFlag::kMaybeAssigned)((void) 0);
218 Variable* var = DeclareClassVariable(
219 ast_value_factory,
220 ast_value_factory->GetString(name,
221 SharedStringAccessGuardIfNeeded(isolate)),
222 kNoSourcePosition);
223 var->AllocateTo(VariableLocation::CONTEXT,
224 Context::MIN_CONTEXT_SLOTS + index);
225 }
226
227 DCHECK(scope_info->HasPositionInfo())((void) 0);
228 set_start_position(scope_info->StartPosition());
229 set_end_position(scope_info->EndPosition());
230}
231template ClassScope::ClassScope(Isolate* isolate, Zone* zone,
232 AstValueFactory* ast_value_factory,
233 Handle<ScopeInfo> scope_info);
234template ClassScope::ClassScope(LocalIsolate* isolate, Zone* zone,
235 AstValueFactory* ast_value_factory,
236 Handle<ScopeInfo> scope_info);
237
238Scope::Scope(Zone* zone, ScopeType scope_type,
239 AstValueFactory* ast_value_factory, Handle<ScopeInfo> scope_info)
240 : outer_scope_(nullptr),
241 variables_(zone),
242 scope_info_(scope_info),
243 scope_type_(scope_type) {
244 DCHECK(!scope_info.is_null())((void) 0);
245 SetDefaults();
246#ifdef DEBUG
247 already_resolved_ = true;
248#endif
249 set_language_mode(scope_info->language_mode());
250 DCHECK_EQ(ContextHeaderLength(), num_heap_slots_)((void) 0);
251 private_name_lookup_skips_outer_class_ =
252 scope_info->PrivateNameLookupSkipsOuterClass();
253 // We don't really need to use the preparsed scope data; this is just to
254 // shorten the recursion in SetMustUsePreparseData.
255 must_use_preparsed_scope_data_ = true;
256
257 if (scope_type == BLOCK_SCOPE) {
258 // Set is_block_scope_for_object_literal_ based on the existince of the home
259 // object variable (we don't store it explicitly).
260 DCHECK_NOT_NULL(ast_value_factory)((void) 0);
261 int home_object_index = scope_info->ContextSlotIndex(
262 ast_value_factory->dot_home_object_string()->string());
263 DCHECK_IMPLIES(home_object_index >= 0,((void) 0)
264 scope_type == CLASS_SCOPE || scope_type == BLOCK_SCOPE)((void) 0);
265 if (home_object_index >= 0) {
266 is_block_scope_for_object_literal_ = true;
267 }
268 }
269}
270
271DeclarationScope::DeclarationScope(Zone* zone, ScopeType scope_type,
272 AstValueFactory* ast_value_factory,
273 Handle<ScopeInfo> scope_info)
274 : Scope(zone, scope_type, ast_value_factory, scope_info),
275 function_kind_(scope_info->function_kind()),
276 params_(0, zone) {
277 DCHECK_NE(scope_type, SCRIPT_SCOPE)((void) 0);
278 SetDefaults();
279 if (scope_info->SloppyEvalCanExtendVars()) {
280 DCHECK(!is_eval_scope())((void) 0);
281 sloppy_eval_can_extend_vars_ = true;
282 }
283 if (scope_info->ClassScopeHasPrivateBrand()) {
284 DCHECK(IsClassConstructor(function_kind()))((void) 0);
285 class_scope_has_private_brand_ = true;
286 }
287}
288
289Scope::Scope(Zone* zone, const AstRawString* catch_variable_name,
290 MaybeAssignedFlag maybe_assigned, Handle<ScopeInfo> scope_info)
291 : outer_scope_(nullptr),
292 variables_(zone),
293 scope_info_(scope_info),
294 scope_type_(CATCH_SCOPE) {
295 SetDefaults();
296#ifdef DEBUG
297 already_resolved_ = true;
298#endif
299 // Cache the catch variable, even though it's also available via the
300 // scope_info, as the parser expects that a catch scope always has the catch
301 // variable as first and only variable.
302 bool was_added;
303 Variable* variable =
304 Declare(zone, catch_variable_name, VariableMode::kVar, NORMAL_VARIABLE,
305 kCreatedInitialized, maybe_assigned, &was_added);
306 DCHECK(was_added)((void) 0);
307 AllocateHeapSlot(variable);
308}
309
310void DeclarationScope::SetDefaults() {
311 is_declaration_scope_ = true;
312 has_simple_parameters_ = true;
313#if V8_ENABLE_WEBASSEMBLY1
314 is_asm_module_ = false;
315#endif // V8_ENABLE_WEBASSEMBLY
316 force_eager_compilation_ = false;
317 has_arguments_parameter_ = false;
318 uses_super_property_ = false;
319 has_checked_syntax_ = false;
320 has_this_reference_ = false;
321 has_this_declaration_ =
322 (is_function_scope() && !is_arrow_scope()) || is_module_scope();
323 needs_private_name_context_chain_recalc_ = false;
324 has_rest_ = false;
325 receiver_ = nullptr;
326 new_target_ = nullptr;
327 function_ = nullptr;
328 arguments_ = nullptr;
329 rare_data_ = nullptr;
330 should_eager_compile_ = false;
331 was_lazily_parsed_ = false;
332 is_skipped_function_ = false;
333 preparse_data_builder_ = nullptr;
334 class_scope_has_private_brand_ = false;
335#ifdef DEBUG
336 DeclarationScope* outer_declaration_scope =
337 outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr;
338 is_being_lazily_parsed_ =
339 outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_
340 : false;
341#endif
342}
343
344void Scope::SetDefaults() {
345#ifdef DEBUG
346 scope_name_ = nullptr;
347 already_resolved_ = false;
348 needs_migration_ = false;
349#endif
350 inner_scope_ = nullptr;
351 sibling_ = nullptr;
352 unresolved_list_.Clear();
353
354 start_position_ = kNoSourcePosition;
355 end_position_ = kNoSourcePosition;
356
357 calls_eval_ = false;
358 sloppy_eval_can_extend_vars_ = false;
359 scope_nonlinear_ = false;
360 is_hidden_ = false;
361 is_debug_evaluate_scope_ = false;
362
363 inner_scope_calls_eval_ = false;
364 force_context_allocation_for_parameters_ = false;
365
366 is_declaration_scope_ = false;
367
368 private_name_lookup_skips_outer_class_ = false;
369
370 must_use_preparsed_scope_data_ = false;
371 is_repl_mode_scope_ = false;
372
373 deserialized_scope_uses_external_cache_ = false;
374
375 needs_home_object_ = false;
376 is_block_scope_for_object_literal_ = false;
377
378 num_stack_slots_ = 0;
379 num_heap_slots_ = ContextHeaderLength();
380
381 set_language_mode(LanguageMode::kSloppy);
382}
383
384bool Scope::HasSimpleParameters() {
385 DeclarationScope* scope = GetClosureScope();
386 return !scope->is_function_scope() || scope->has_simple_parameters();
387}
388
389void DeclarationScope::set_should_eager_compile() {
390 should_eager_compile_ = !was_lazily_parsed_;
391}
392
393#if V8_ENABLE_WEBASSEMBLY1
394void DeclarationScope::set_is_asm_module() { is_asm_module_ = true; }
395
396bool Scope::IsAsmModule() const {
397 return is_function_scope() && AsDeclarationScope()->is_asm_module();
398}
399
400bool Scope::ContainsAsmModule() const {
401 if (IsAsmModule()) return true;
402
403 // Check inner scopes recursively
404 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
405 // Don't check inner functions which won't be eagerly compiled.
406 if (!scope->is_function_scope() ||
407 scope->AsDeclarationScope()->ShouldEagerCompile()) {
408 if (scope->ContainsAsmModule()) return true;
409 }
410 }
411
412 return false;
413}
414#endif // V8_ENABLE_WEBASSEMBLY
415
416template <typename IsolateT>
417Scope* Scope::DeserializeScopeChain(IsolateT* isolate, Zone* zone,
418 ScopeInfo scope_info,
419 DeclarationScope* script_scope,
420 AstValueFactory* ast_value_factory,
421 DeserializationMode deserialization_mode) {
422 // Reconstruct the outer scope chain from a closure's context chain.
423 Scope* current_scope = nullptr;
424 Scope* innermost_scope = nullptr;
425 Scope* outer_scope = nullptr;
426 bool cache_scope_found = false;
427 while (!scope_info.is_null()) {
428 if (scope_info.scope_type() == WITH_SCOPE) {
429 if (scope_info.IsDebugEvaluateScope()) {
430 outer_scope =
431 zone->New<DeclarationScope>(zone, FUNCTION_SCOPE, ast_value_factory,
432 handle(scope_info, isolate));
433 outer_scope->set_is_debug_evaluate_scope();
434 } else {
435 // For scope analysis, debug-evaluate is equivalent to a with scope.
436 outer_scope = zone->New<Scope>(zone, WITH_SCOPE, ast_value_factory,
437 handle(scope_info, isolate));
438 }
439
440 } else if (scope_info.scope_type() == SCRIPT_SCOPE) {
441 // If we reach a script scope, it's the outermost scope. Install the
442 // scope info of this script context onto the existing script scope to
443 // avoid nesting script scopes.
444 if (deserialization_mode == DeserializationMode::kIncludingVariables) {
445 script_scope->SetScriptScopeInfo(handle(scope_info, isolate));
446 }
447 if (scope_info.IsReplModeScope()) script_scope->set_is_repl_mode_scope();
448 DCHECK(!scope_info.HasOuterScopeInfo())((void) 0);
449 break;
450 } else if (scope_info.scope_type() == FUNCTION_SCOPE) {
451 outer_scope = zone->New<DeclarationScope>(
452 zone, FUNCTION_SCOPE, ast_value_factory, handle(scope_info, isolate));
453#if V8_ENABLE_WEBASSEMBLY1
454 if (scope_info.IsAsmModule()) {
455 outer_scope->AsDeclarationScope()->set_is_asm_module();
456 }
457#endif // V8_ENABLE_WEBASSEMBLY
458 } else if (scope_info.scope_type() == EVAL_SCOPE) {
459 outer_scope = zone->New<DeclarationScope>(
460 zone, EVAL_SCOPE, ast_value_factory, handle(scope_info, isolate));
461 } else if (scope_info.scope_type() == CLASS_SCOPE) {
462 outer_scope = zone->New<ClassScope>(isolate, zone, ast_value_factory,
463 handle(scope_info, isolate));
464 } else if (scope_info.scope_type() == BLOCK_SCOPE) {
465 if (scope_info.is_declaration_scope()) {
466 outer_scope = zone->New<DeclarationScope>(
467 zone, BLOCK_SCOPE, ast_value_factory, handle(scope_info, isolate));
468 } else {
469 outer_scope = zone->New<Scope>(zone, BLOCK_SCOPE, ast_value_factory,
470 handle(scope_info, isolate));
471 }
472 } else if (scope_info.scope_type() == MODULE_SCOPE) {
473 outer_scope = zone->New<ModuleScope>(handle(scope_info, isolate),
474 ast_value_factory);
475 } else {
476 DCHECK_EQ(scope_info.scope_type(), CATCH_SCOPE)((void) 0);
477 DCHECK_EQ(scope_info.ContextLocalCount(), 1)((void) 0);
478 DCHECK_EQ(scope_info.ContextLocalMode(0), VariableMode::kVar)((void) 0);
479 DCHECK_EQ(scope_info.ContextLocalInitFlag(0), kCreatedInitialized)((void) 0);
480 DCHECK(scope_info.HasInlinedLocalNames())((void) 0);
481 String name = scope_info.ContextInlinedLocalName(0);
482 MaybeAssignedFlag maybe_assigned =
483 scope_info.ContextLocalMaybeAssignedFlag(0);
484 outer_scope =
485 zone->New<Scope>(zone,
486 ast_value_factory->GetString(
487 name, SharedStringAccessGuardIfNeeded(isolate)),
488 maybe_assigned, handle(scope_info, isolate));
489 }
490 if (deserialization_mode == DeserializationMode::kScopesOnly) {
491 outer_scope->scope_info_ = Handle<ScopeInfo>::null();
492 }
493
494 if (cache_scope_found) {
495 outer_scope->set_deserialized_scope_uses_external_cache();
496 } else {
497 DCHECK(!cache_scope_found)((void) 0);
498 cache_scope_found =
499 outer_scope->is_declaration_scope() && !outer_scope->is_eval_scope();
500 }
501
502 if (current_scope != nullptr) {
503 outer_scope->AddInnerScope(current_scope);
504 }
505 current_scope = outer_scope;
506 if (innermost_scope == nullptr) innermost_scope = current_scope;
507 scope_info = scope_info.HasOuterScopeInfo() ? scope_info.OuterScopeInfo()
508 : ScopeInfo();
509 }
510
511 if (deserialization_mode == DeserializationMode::kIncludingVariables) {
512 SetScriptScopeInfo(isolate, script_scope);
513 }
514
515 if (innermost_scope == nullptr) return script_scope;
516 script_scope->AddInnerScope(current_scope);
517 return innermost_scope;
518}
519
520template <typename IsolateT>
521void Scope::SetScriptScopeInfo(IsolateT* isolate,
522 DeclarationScope* script_scope) {
523 if (script_scope->scope_info_.is_null()) {
524 script_scope->SetScriptScopeInfo(
525 ReadOnlyRoots(isolate).global_this_binding_scope_info_handle());
526 }
527}
528
529template EXPORT_TEMPLATE_DEFINE(
530 V8_EXPORT_PRIVATE) void Scope::SetScriptScopeInfo(Isolate* isolate,
531 DeclarationScope*
532 script_scope);
533template EXPORT_TEMPLATE_DEFINE(
534 V8_EXPORT_PRIVATE) void Scope::SetScriptScopeInfo(LocalIsolate* isolate,
535 DeclarationScope*
536 script_scope);
537
538template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
539 Scope* Scope::DeserializeScopeChain(
540 Isolate* isolate, Zone* zone, ScopeInfo scope_info,
541 DeclarationScope* script_scope, AstValueFactory* ast_value_factory,
542 DeserializationMode deserialization_mode);
543template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
544 Scope* Scope::DeserializeScopeChain(
545 LocalIsolate* isolate, Zone* zone, ScopeInfo scope_info,
546 DeclarationScope* script_scope, AstValueFactory* ast_value_factory,
547 DeserializationMode deserialization_mode);
548
549#ifdef DEBUG
550bool Scope::IsReparsedMemberInitializerScope() const {
551 return is_declaration_scope() &&
552 IsClassMembersInitializerFunction(
553 AsDeclarationScope()->function_kind()) &&
554 outer_scope()->AsClassScope()->is_reparsed_class_scope();
555}
556#endif
557
558DeclarationScope* Scope::AsDeclarationScope() {
559 DCHECK(is_declaration_scope())((void) 0);
560 return static_cast<DeclarationScope*>(this);
561}
562
563const DeclarationScope* Scope::AsDeclarationScope() const {
564 DCHECK(is_declaration_scope())((void) 0);
565 return static_cast<const DeclarationScope*>(this);
566}
567
568ModuleScope* Scope::AsModuleScope() {
569 DCHECK(is_module_scope())((void) 0);
570 return static_cast<ModuleScope*>(this);
571}
572
573const ModuleScope* Scope::AsModuleScope() const {
574 DCHECK(is_module_scope())((void) 0);
575 return static_cast<const ModuleScope*>(this);
576}
577
578ClassScope* Scope::AsClassScope() {
579 DCHECK(is_class_scope())((void) 0);
580 return static_cast<ClassScope*>(this);
581}
582
583const ClassScope* Scope::AsClassScope() const {
584 DCHECK(is_class_scope())((void) 0);
585 return static_cast<const ClassScope*>(this);
586}
587
588void DeclarationScope::DeclareSloppyBlockFunction(
589 SloppyBlockFunctionStatement* sloppy_block_function) {
590 sloppy_block_functions_.Add(sloppy_block_function);
591}
592
593void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
594 DCHECK(is_sloppy(language_mode()))((void) 0);
595 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() ||((void) 0)
596 (is_block_scope() && outer_scope()->is_function_scope()))((void) 0);
597 DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_)((void) 0);
598 DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_)((void) 0);
599
600 if (sloppy_block_functions_.is_empty()) return;
601
602 // In case of complex parameters the current scope is the body scope and the
603 // parameters are stored in the outer scope.
604 Scope* parameter_scope = HasSimpleParameters() ? this : outer_scope_;
605 DCHECK(parameter_scope->is_function_scope() || is_eval_scope() ||((void) 0)
606 is_script_scope())((void) 0);
607
608 DeclarationScope* decl_scope = GetNonEvalDeclarationScope();
609 Scope* outer_scope = decl_scope->outer_scope();
610
611 // For each variable which is used as a function declaration in a sloppy
612 // block,
613 for (SloppyBlockFunctionStatement* sloppy_block_function :
614 sloppy_block_functions_) {
615 const AstRawString* name = sloppy_block_function->name();
616
617 // If the variable wouldn't conflict with a lexical declaration
618 // or parameter,
619
620 // Check if there's a conflict with a parameter.
621 Variable* maybe_parameter = parameter_scope->LookupLocal(name);
622 if (maybe_parameter != nullptr && maybe_parameter->is_parameter()) {
623 continue;
624 }
625
626 // Check if there's a conflict with a lexical declaration
627 Scope* query_scope = sloppy_block_function->scope()->outer_scope();
628 bool should_hoist = true;
629
630 // It is not sufficient to just do a Lookup on query_scope: for
631 // example, that does not prevent hoisting of the function in
632 // `{ let e; try {} catch (e) { function e(){} } }`
633 //
634 // Don't use a generic cache scope, as the cache scope would be the outer
635 // scope and we terminate the iteration there anyway.
636 do {
637 Variable* var = query_scope->LookupInScopeOrScopeInfo(name, query_scope);
638 if (var != nullptr && IsLexicalVariableMode(var->mode())) {
639 should_hoist = false;
640 break;
641 }
642 query_scope = query_scope->outer_scope();
643 } while (query_scope != outer_scope);
644
645 if (!should_hoist) continue;
646
647 if (factory) {
648 DCHECK(!is_being_lazily_parsed_)((void) 0);
649 int pos = sloppy_block_function->position();
650 bool ok = true;
651 bool was_added;
652 auto declaration = factory->NewVariableDeclaration(pos);
653 // Based on the preceding checks, it doesn't matter what we pass as
654 // sloppy_mode_block_scope_function_redefinition.
655 Variable* var = DeclareVariable(
656 declaration, name, pos, VariableMode::kVar, NORMAL_VARIABLE,
657 Variable::DefaultInitializationFlag(VariableMode::kVar), &was_added,
658 nullptr, &ok);
659 DCHECK(ok)((void) 0);
660 VariableProxy* source =
661 factory->NewVariableProxy(sloppy_block_function->var());
662 VariableProxy* target = factory->NewVariableProxy(var);
663 Assignment* assignment = factory->NewAssignment(
664 sloppy_block_function->init(), target, source, pos);
665 assignment->set_lookup_hoisting_mode(LookupHoistingMode::kLegacySloppy);
666 Statement* statement = factory->NewExpressionStatement(assignment, pos);
667 sloppy_block_function->set_statement(statement);
668 } else {
669 DCHECK(is_being_lazily_parsed_)((void) 0);
670 bool was_added;
671 Variable* var = DeclareVariableName(name, VariableMode::kVar, &was_added);
672 if (sloppy_block_function->init() == Token::ASSIGN) {
673 var->SetMaybeAssigned();
674 }
675 }
676 }
677}
678
679bool DeclarationScope::Analyze(ParseInfo* info) {
680 RCS_SCOPE(info->runtime_call_stats(),
681 RuntimeCallCounterId::kCompileScopeAnalysis,
682 RuntimeCallStats::kThreadSpecific);
683 DCHECK_NOT_NULL(info->literal())((void) 0);
684 DeclarationScope* scope = info->literal()->scope();
685
686 base::Optional<AllowHandleDereference> allow_deref;
687#ifdef DEBUG
688 if (scope->outer_scope() && !scope->outer_scope()->scope_info_.is_null()) {
689 allow_deref.emplace();
690 }
691#endif
692
693 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) {
694 AstNodeFactory factory(info->ast_value_factory(), info->zone());
695 scope->HoistSloppyBlockFunctions(&factory);
696 }
697
698 // We are compiling one of four cases:
699 // 1) top-level code,
700 // 2) a function/eval/module on the top-level
701 // 4) a class member initializer function scope
702 // 3) 4 function/eval in a scope that was already resolved.
703 DCHECK(scope->is_script_scope() || scope->outer_scope()->is_script_scope() ||((void) 0)
704 scope->IsReparsedMemberInitializerScope() ||((void) 0)
705 scope->outer_scope()->already_resolved_)((void) 0);
706
707 // The outer scope is never lazy.
708 scope->set_should_eager_compile();
709
710 if (scope->must_use_preparsed_scope_data_) {
711 DCHECK_EQ(scope->scope_type_, ScopeType::FUNCTION_SCOPE)((void) 0);
712 allow_deref.emplace();
713 info->consumed_preparse_data()->RestoreScopeAllocationData(
714 scope, info->ast_value_factory(), info->zone());
715 }
716
717 if (!scope->AllocateVariables(info)) return false;
718 scope->GetScriptScope()->RewriteReplGlobalVariables();
719
720#ifdef DEBUG
721 if (FLAG_print_scopes) {
722 PrintF("Global scope:\n");
723 scope->Print();
724 }
725 scope->CheckScopePositions();
726 scope->CheckZones();
727#endif
728
729 return true;
730}
731
732void DeclarationScope::DeclareThis(AstValueFactory* ast_value_factory) {
733 DCHECK(has_this_declaration())((void) 0);
734
735 bool derived_constructor = IsDerivedConstructor(function_kind_);
736
737 receiver_ = zone()->New<Variable>(
738 this, ast_value_factory->this_string(),
739 derived_constructor ? VariableMode::kConst : VariableMode::kVar,
740 THIS_VARIABLE,
741 derived_constructor ? kNeedsInitialization : kCreatedInitialized,
742 kNotAssigned);
743 locals_.Add(receiver_);
744}
745
746void DeclarationScope::DeclareArguments(AstValueFactory* ast_value_factory) {
747 DCHECK(is_function_scope())((void) 0);
748 DCHECK(!is_arrow_scope())((void) 0);
749
750 // Because when arguments_ is not nullptr, we already declared
751 // "arguments exotic object" to add it into parameters before
752 // impl()->InsertShadowingVarBindingInitializers, so here
753 // only declare "arguments exotic object" when arguments_
754 // is nullptr
755 if (arguments_ != nullptr) {
756 return;
757 }
758
759 // Declare 'arguments' variable which exists in all non arrow functions. Note
760 // that it might never be accessed, in which case it won't be allocated during
761 // variable allocation.
762 bool was_added = false;
763
764 arguments_ =
765 Declare(zone(), ast_value_factory->arguments_string(), VariableMode::kVar,
766 NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
767 // According to ES#sec-functiondeclarationinstantiation step 18
768 // we should set argumentsObjectNeeded to false if has lexical
769 // declared arguments only when hasParameterExpressions is false
770 if (!was_added && IsLexicalVariableMode(arguments_->mode()) &&
771 has_simple_parameters_) {
772 // Check if there's lexically declared variable named arguments to avoid
773 // redeclaration. See ES#sec-functiondeclarationinstantiation, step 20.
774 arguments_ = nullptr;
775 }
776}
777
778void DeclarationScope::DeclareDefaultFunctionVariables(
779 AstValueFactory* ast_value_factory) {
780 DCHECK(is_function_scope())((void) 0);
781 DCHECK(!is_arrow_scope())((void) 0);
782
783 DeclareThis(ast_value_factory);
784 bool was_added;
785 new_target_ = Declare(zone(), ast_value_factory->new_target_string(),
786 VariableMode::kConst, NORMAL_VARIABLE,
787 kCreatedInitialized, kNotAssigned, &was_added);
788 DCHECK(was_added)((void) 0);
789
790 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) ||
791 IsAccessorFunction(function_kind_)) {
792 EnsureRareData()->this_function = Declare(
793 zone(), ast_value_factory->this_function_string(), VariableMode::kConst,
794 NORMAL_VARIABLE, kCreatedInitialized, kNotAssigned, &was_added);
795 DCHECK(was_added)((void) 0);
796 }
797}
798
799Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name,
800 Scope* cache) {
801 DCHECK(is_function_scope())((void) 0);
802 DCHECK_NULL(function_)((void) 0);
803 if (cache == nullptr) cache = this;
804 DCHECK(this->IsOuterScopeOf(cache))((void) 0);
805 DCHECK_NULL(cache->variables_.Lookup(name))((void) 0);
806 VariableKind kind = is_sloppy(language_mode()) ? SLOPPY_FUNCTION_NAME_VARIABLE
807 : NORMAL_VARIABLE;
808 function_ = zone()->New<Variable>(this, name, VariableMode::kConst, kind,
809 kCreatedInitialized);
810 if (sloppy_eval_can_extend_vars()) {
811 cache->NonLocal(name, VariableMode::kDynamic);
812 } else {
813 cache->variables_.Add(function_);
814 }
815 return function_;
816}
817
818Variable* DeclarationScope::DeclareGeneratorObjectVar(
819 const AstRawString* name) {
820 DCHECK(is_function_scope() || is_module_scope() || is_repl_mode_scope())((void) 0);
821 DCHECK_NULL(generator_object_var())((void) 0);
822
823 Variable* result = EnsureRareData()->generator_object =
824 NewTemporary(name, kNotAssigned);
825 result->set_is_used();
826 return result;
827}
828
829Scope* Scope::FinalizeBlockScope() {
830 DCHECK(is_block_scope())((void) 0);
831#ifdef DEBUG
832 DCHECK_NE(sibling_, this)((void) 0);
833#endif
834
835 if (variables_.occupancy() > 0 ||
836 (is_declaration_scope() &&
837 AsDeclarationScope()->sloppy_eval_can_extend_vars())) {
838 return this;
839 }
840
841 DCHECK(!is_class_scope())((void) 0);
842
843 // Remove this scope from outer scope.
844 outer_scope()->RemoveInnerScope(this);
845
846 // Reparent inner scopes.
847 if (inner_scope_ != nullptr) {
848 Scope* scope = inner_scope_;
849 scope->outer_scope_ = outer_scope();
850 while (scope->sibling_ != nullptr) {
851 scope = scope->sibling_;
852 scope->outer_scope_ = outer_scope();
853 }
854 scope->sibling_ = outer_scope()->inner_scope_;
855 outer_scope()->inner_scope_ = inner_scope_;
856 inner_scope_ = nullptr;
857 }
858
859 // Move unresolved variables
860 if (!unresolved_list_.is_empty()) {
861 outer_scope()->unresolved_list_.Prepend(std::move(unresolved_list_));
862 unresolved_list_.Clear();
863 }
864
865 if (inner_scope_calls_eval_) outer_scope()->inner_scope_calls_eval_ = true;
866
867 // No need to propagate sloppy_eval_can_extend_vars_, since if it was relevant
868 // to this scope we would have had to bail out at the top.
869 DCHECK(!is_declaration_scope() ||((void) 0)
870 !AsDeclarationScope()->sloppy_eval_can_extend_vars())((void) 0);
871
872 // This block does not need a context.
873 num_heap_slots_ = 0;
874
875 // Mark scope as removed by making it its own sibling.
876#ifdef DEBUG
877 sibling_ = this;
878#endif
879
880 return nullptr;
881}
882
883void DeclarationScope::AddLocal(Variable* var) {
884 DCHECK(!already_resolved_)((void) 0);
885 // Temporaries are only placed in ClosureScopes.
886 DCHECK_EQ(GetClosureScope(), this)((void) 0);
887 locals_.Add(var);
888}
889
890void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
891 DCHECK(!IsCleared())((void) 0);
892 DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_)((void) 0);
893 DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer())((void) 0);
894 DCHECK_EQ(new_parent, new_parent->GetClosureScope())((void) 0);
895 DCHECK_NULL(new_parent->inner_scope_)((void) 0);
896 DCHECK(new_parent->unresolved_list_.is_empty())((void) 0);
897 Scope* inner_scope = new_parent->sibling_;
898 if (inner_scope != top_inner_scope_) {
899 for (; inner_scope->sibling() != top_inner_scope_;
900 inner_scope = inner_scope->sibling()) {
901 inner_scope->outer_scope_ = new_parent;
902 if (inner_scope->inner_scope_calls_eval_) {
903 new_parent->inner_scope_calls_eval_ = true;
904 }
905 DCHECK_NE(inner_scope, new_parent)((void) 0);
906 }
907 inner_scope->outer_scope_ = new_parent;
908 if (inner_scope->inner_scope_calls_eval_) {
909 new_parent->inner_scope_calls_eval_ = true;
910 }
911 new_parent->inner_scope_ = new_parent->sibling_;
912 inner_scope->sibling_ = nullptr;
913 // Reset the sibling rather than the inner_scope_ since we
914 // want to keep new_parent there.
915 new_parent->sibling_ = top_inner_scope_;
916 }
917
918 Scope* outer_scope = outer_scope_and_calls_eval_.GetPointer();
919 new_parent->unresolved_list_.MoveTail(&outer_scope->unresolved_list_,
920 top_unresolved_);
921
922 // Move temporaries allocated for complex parameter initializers.
923 DeclarationScope* outer_closure = outer_scope->GetClosureScope();
924 for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
925 Variable* local = *it;
926 DCHECK_EQ(VariableMode::kTemporary, local->mode())((void) 0);
927 DCHECK_EQ(local->scope(), local->scope()->GetClosureScope())((void) 0);
928 DCHECK_NE(local->scope(), new_parent)((void) 0);
929 local->set_scope(new_parent);
930 }
931 new_parent->locals_.MoveTail(outer_closure->locals(), top_local_);
932 outer_closure->locals_.Rewind(top_local_);
933
934 // Move eval calls since Snapshot's creation into new_parent.
935 if (outer_scope_and_calls_eval_->calls_eval_) {
936 new_parent->RecordDeclarationScopeEvalCall();
937 new_parent->inner_scope_calls_eval_ = true;
938 }
939
940 // We are in the arrow function case. The calls eval we may have recorded
941 // is intended for the inner scope and we should simply restore the
942 // original "calls eval" flag of the outer scope.
943 RestoreEvalFlag();
944 Clear();
945}
946
947void Scope::ReplaceOuterScope(Scope* outer) {
948 DCHECK_NOT_NULL(outer)((void) 0);
949 DCHECK_NOT_NULL(outer_scope_)((void) 0);
950 DCHECK(!already_resolved_)((void) 0);
951 outer_scope_->RemoveInnerScope(this);
952 outer->AddInnerScope(this);
953 outer_scope_ = outer;
954}
955
956Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
957 DCHECK(!scope_info_.is_null())((void) 0);
958 DCHECK(this->IsOuterScopeOf(cache))((void) 0);
959 DCHECK(!cache->deserialized_scope_uses_external_cache())((void) 0);
960 // The case where where the cache can be another scope is when the cache scope
961 // is the last scope that doesn't use an external cache.
962 DCHECK_IMPLIES(((void) 0)
963 cache != this,((void) 0)
964 cache->outer_scope()->deserialized_scope_uses_external_cache())((void) 0);
965 DCHECK_NULL(cache->variables_.Lookup(name))((void) 0);
966 DisallowGarbageCollection no_gc;
967
968 String name_handle = *name->string();
969 ScopeInfo scope_info = *scope_info_;
970 // The Scope is backed up by ScopeInfo. This means it cannot operate in a
971 // heap-independent mode, and all strings must be internalized immediately. So
972 // it's ok to get the Handle<String> here.
973 bool found = false;
974
975 VariableLocation location;
976 int index;
977 VariableLookupResult lookup_result;
978
979 {
980 location = VariableLocation::CONTEXT;
981 index = scope_info.ContextSlotIndex(name->string(), &lookup_result);
982 found = index >= 0;
983 }
984
985 if (!found && is_module_scope()) {
986 location = VariableLocation::MODULE;
987 index = scope_info.ModuleIndex(name_handle, &lookup_result.mode,
988 &lookup_result.init_flag,
989 &lookup_result.maybe_assigned_flag);
990 found = index != 0;
991 }
992
993 if (!found) {
994 index = scope_info.FunctionContextSlotIndex(name_handle);
995 if (index < 0) return nullptr; // Nowhere found.
996 Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache);
997 DCHECK_EQ(VariableMode::kConst, var->mode())((void) 0);
998 var->AllocateTo(VariableLocation::CONTEXT, index);
999 return cache->variables_.Lookup(name);
1000 }
1001
1002 if (!is_module_scope()) {
1003 DCHECK_NE(index, scope_info.ReceiverContextSlotIndex())((void) 0);
1004 }
1005
1006 bool was_added;
1007 Variable* var = cache->variables_.Declare(
1008 zone(), this, name, lookup_result.mode, NORMAL_VARIABLE,
1009 lookup_result.init_flag, lookup_result.maybe_assigned_flag,
1010 IsStaticFlag::kNotStatic, &was_added);
1011 DCHECK(was_added)((void) 0);
1012 var->AllocateTo(location, index);
1013 return var;
1014}
1015
1016Variable* DeclarationScope::DeclareParameter(const AstRawString* name,
1017 VariableMode mode,
1018 bool is_optional, bool is_rest,
1019 AstValueFactory* ast_value_factory,
1020 int position) {
1021 DCHECK(!already_resolved_)((void) 0);
1022 DCHECK(is_function_scope() || is_module_scope())((void) 0);
1023 DCHECK(!has_rest_)((void) 0);
1024 DCHECK(!is_optional || !is_rest)((void) 0);
1025 DCHECK(!is_being_lazily_parsed_)((void) 0);
1026 DCHECK(!was_lazily_parsed_)((void) 0);
1027 Variable* var;
1028 if (mode == VariableMode::kTemporary) {
1029 var = NewTemporary(name);
1030 } else {
1031 var = LookupLocal(name);
1032 DCHECK_EQ(mode, VariableMode::kVar)((void) 0);
1033 DCHECK(var->is_parameter())((void) 0);
1034 }
1035 has_rest_ = is_rest;
1036 var->set_initializer_position(position);
1037 params_.Add(var, zone());
1038 if (!is_rest) ++num_parameters_;
1039 if (name == ast_value_factory->arguments_string()) {
1040 has_arguments_parameter_ = true;
1041 }
1042 // Params are automatically marked as used to make sure that the debugger and
1043 // function.arguments sees them.
1044 // TODO(verwaest): Reevaluate whether we always need to do this, since
1045 // strict-mode function.arguments does not make the arguments available.
1046 var->set_is_used();
1047 return var;
1048}
1049
1050void DeclarationScope::RecordParameter(bool is_rest) {
1051 DCHECK(!already_resolved_)((void) 0);
1052 DCHECK(is_function_scope() || is_module_scope())((void) 0);
1053 DCHECK(is_being_lazily_parsed_)((void) 0);
1054 DCHECK(!has_rest_)((void) 0);
1055 has_rest_ = is_rest;
1056 if (!is_rest) ++num_parameters_;
1057}
1058
1059Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
1060 VariableKind kind, bool* was_added,
1061 InitializationFlag init_flag) {
1062 DCHECK(!already_resolved_)((void) 0);
1063 // Private methods should be declared with ClassScope::DeclarePrivateName()
1064 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode))((void) 0);
1065 // This function handles VariableMode::kVar, VariableMode::kLet, and
1066 // VariableMode::kConst modes. VariableMode::kDynamic variables are
1067 // introduced during variable allocation, and VariableMode::kTemporary
1068 // variables are allocated via NewTemporary().
1069 DCHECK(IsDeclaredVariableMode(mode))((void) 0);
1070 DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(),((void) 0)
1071 mode == VariableMode::kVar || mode == VariableMode::kLet ||((void) 0)
1072 mode == VariableMode::kConst)((void) 0);
1073 DCHECK(!GetDeclarationScope()->was_lazily_parsed())((void) 0);
1074 Variable* var =
1075 Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added);
1076
1077 // Pessimistically assume that top-level variables will be assigned and used.
1078 //
1079 // Top-level variables in a script can be accessed by other scripts or even
1080 // become global properties. While this does not apply to top-level variables
1081 // in a module (assuming they are not exported), we must still mark these as
1082 // assigned because they might be accessed by a lazily parsed top-level
1083 // function, which, for efficiency, we preparse without variable tracking.
1084 if (is_script_scope() || is_module_scope()) {
1085 if (mode != VariableMode::kConst) var->SetMaybeAssigned();
1086 var->set_is_used();
1087 }
1088
1089 return var;
1090}
1091
1092Variable* Scope::DeclareVariable(
1093 Declaration* declaration, const AstRawString* name, int pos,
1094 VariableMode mode, VariableKind kind, InitializationFlag init,
1095 bool* was_added, bool* sloppy_mode_block_scope_function_redefinition,
1096 bool* ok) {
1097 // Private methods should be declared with ClassScope::DeclarePrivateName()
1098 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode))((void) 0);
1099 DCHECK(IsDeclaredVariableMode(mode))((void) 0);
1100 DCHECK(!already_resolved_)((void) 0);
1101 DCHECK(!GetDeclarationScope()->is_being_lazily_parsed())((void) 0);
1102 DCHECK(!GetDeclarationScope()->was_lazily_parsed())((void) 0);
1103
1104 if (mode == VariableMode::kVar && !is_declaration_scope()) {
1105 return GetDeclarationScope()->DeclareVariable(
1106 declaration, name, pos, mode, kind, init, was_added,
1107 sloppy_mode_block_scope_function_redefinition, ok);
1108 }
1109 DCHECK(!is_catch_scope())((void) 0);
1110 DCHECK(!is_with_scope())((void) 0);
1111 DCHECK(is_declaration_scope() ||((void) 0)
1112 (IsLexicalVariableMode(mode) && is_block_scope()))((void) 0);
1113
1114 DCHECK_NOT_NULL(name)((void) 0);
1115
1116 Variable* var = LookupLocal(name);
1117 // Declare the variable in the declaration scope.
1118 *was_added = var == nullptr;
1119 if (V8_LIKELY(*was_added)(__builtin_expect(!!(*was_added), 1))) {
1120 if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) &&(__builtin_expect(!!(is_eval_scope() && is_sloppy(language_mode
()) && mode == VariableMode::kVar), 0))
1121 mode == VariableMode::kVar)(__builtin_expect(!!(is_eval_scope() && is_sloppy(language_mode
()) && mode == VariableMode::kVar), 0))
) {
1122 // In a var binding in a sloppy direct eval, pollute the enclosing scope
1123 // with this new binding by doing the following:
1124 // The proxy is bound to a lookup variable to force a dynamic declaration
1125 // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
1126 DCHECK_EQ(NORMAL_VARIABLE, kind)((void) 0);
1127 var = NonLocal(name, VariableMode::kDynamic);
1128 // Mark the var as used in case anyone outside the eval wants to use it.
1129 var->set_is_used();
1130 } else {
1131 // Declare the name.
1132 var = DeclareLocal(name, mode, kind, was_added, init);
1133 DCHECK(*was_added)((void) 0);
1134 }
1135 } else {
1136 var->SetMaybeAssigned();
1137 if (V8_UNLIKELY(IsLexicalVariableMode(mode) ||(__builtin_expect(!!(IsLexicalVariableMode(mode) || IsLexicalVariableMode
(var->mode())), 0))
1138 IsLexicalVariableMode(var->mode()))(__builtin_expect(!!(IsLexicalVariableMode(mode) || IsLexicalVariableMode
(var->mode())), 0))
) {
1139 // The name was declared in this scope before; check for conflicting
1140 // re-declarations. We have a conflict if either of the declarations is
1141 // not a var (in script scope, we also have to ignore legacy const for
1142 // compatibility). There is similar code in runtime.cc in the Declare
1143 // functions. The function CheckConflictingVarDeclarations checks for
1144 // var and let bindings from different scopes whereas this is a check
1145 // for conflicting declarations within the same scope. This check also
1146 // covers the special case
1147 //
1148 // function () { let x; { var x; } }
1149 //
1150 // because the var declaration is hoisted to the function scope where
1151 // 'x' is already bound.
1152 //
1153 // In harmony we treat re-declarations as early errors. See ES5 16 for a
1154 // definition of early errors.
1155 //
1156 // Allow duplicate function decls for web compat, see bug 4693.
1157 *ok = var->is_sloppy_block_function() &&
1158 kind == SLOPPY_BLOCK_FUNCTION_VARIABLE;
1159 *sloppy_mode_block_scope_function_redefinition = *ok;
1160 }
1161 }
1162 DCHECK_NOT_NULL(var)((void) 0);
1163
1164 // We add a declaration node for every declaration. The compiler
1165 // will only generate code if necessary. In particular, declarations
1166 // for inner local variables that do not represent functions won't
1167 // result in any generated code.
1168 //
1169 // This will lead to multiple declaration nodes for the
1170 // same variable if it is declared several times. This is not a
1171 // semantic issue, but it may be a performance issue since it may
1172 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls.
1173 decls_.Add(declaration);
1174 declaration->set_var(var);
1175 return var;
1176}
1177
1178Variable* Scope::DeclareVariableName(const AstRawString* name,
1179 VariableMode mode, bool* was_added,
1180 VariableKind kind) {
1181 DCHECK(IsDeclaredVariableMode(mode))((void) 0);
1182 DCHECK(!already_resolved_)((void) 0);
1183 DCHECK(GetDeclarationScope()->is_being_lazily_parsed())((void) 0);
1184 // Private methods should be declared with ClassScope::DeclarePrivateName()
1185 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode))((void) 0);
1186 if (mode == VariableMode::kVar && !is_declaration_scope()) {
1187 return GetDeclarationScope()->DeclareVariableName(name, mode, was_added,
1188 kind);
1189 }
1190 DCHECK(!is_with_scope())((void) 0);
1191 DCHECK(!is_eval_scope())((void) 0);
1192 DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode))((void) 0);
1193 DCHECK(scope_info_.is_null())((void) 0);
1194
1195 // Declare the variable in the declaration scope.
1196 Variable* var = DeclareLocal(name, mode, kind, was_added);
1197 if (!*was_added) {
1198 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) {
1199 if (!var->is_sloppy_block_function() ||
1200 kind != SLOPPY_BLOCK_FUNCTION_VARIABLE) {
1201 // Duplicate functions are allowed in the sloppy mode, but if this is
1202 // not a function declaration, it's an error. This is an error PreParser
1203 // hasn't previously detected.
1204 return nullptr;
1205 }
1206 // Sloppy block function redefinition.
1207 }
1208 var->SetMaybeAssigned();
1209 }
1210 var->set_is_used();
1211 return var;
1212}
1213
1214Variable* Scope::DeclareCatchVariableName(const AstRawString* name) {
1215 DCHECK(!already_resolved_)((void) 0);
1216 DCHECK(is_catch_scope())((void) 0);
1217 DCHECK(scope_info_.is_null())((void) 0);
1218
1219 bool was_added;
1220 Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE,
1221 kCreatedInitialized, kNotAssigned, &was_added);
1222 DCHECK(was_added)((void) 0);
1223 return result;
1224}
1225
1226void Scope::AddUnresolved(VariableProxy* proxy) {
1227 DCHECK(!already_resolved_)((void) 0);
1228 DCHECK(!proxy->is_resolved())((void) 0);
1229 unresolved_list_.Add(proxy);
1230}
1231
1232Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
1233 VariableKind kind,
1234 Scope* cache) {
1235 DCHECK(is_script_scope())((void) 0);
1236 bool was_added;
1237 return cache->variables_.Declare(
1238 zone(), this, name, VariableMode::kDynamicGlobal, kind,
1239 kCreatedInitialized, kNotAssigned, IsStaticFlag::kNotStatic, &was_added);
1240 // TODO(neis): Mark variable as maybe-assigned?
1241}
1242
1243bool Scope::RemoveUnresolved(VariableProxy* var) {
1244 return unresolved_list_.Remove(var);
1245}
1246
1247void Scope::DeleteUnresolved(VariableProxy* var) {
1248 DCHECK(unresolved_list_.Contains(var))((void) 0);
1249 var->mark_removed_from_unresolved();
1250}
1251
1252Variable* Scope::NewTemporary(const AstRawString* name) {
1253 return NewTemporary(name, kMaybeAssigned);
1254}
1255
1256Variable* Scope::NewTemporary(const AstRawString* name,
1257 MaybeAssignedFlag maybe_assigned) {
1258 DeclarationScope* scope = GetClosureScope();
1259 Variable* var = zone()->New<Variable>(scope, name, VariableMode::kTemporary,
1260 NORMAL_VARIABLE, kCreatedInitialized);
1261 scope->AddLocal(var);
1262 if (maybe_assigned == kMaybeAssigned) var->SetMaybeAssigned();
1263 return var;
1264}
1265
1266Declaration* DeclarationScope::CheckConflictingVarDeclarations(
1267 bool* allowed_catch_binding_var_redeclaration) {
1268 if (has_checked_syntax_) return nullptr;
1269 for (Declaration* decl : decls_) {
1270 // Lexical vs lexical conflicts within the same scope have already been
1271 // captured in Parser::Declare. The only conflicts we still need to check
1272 // are lexical vs nested var.
1273 if (decl->IsVariableDeclaration() &&
1274 decl->AsVariableDeclaration()->AsNested() != nullptr) {
1275 Scope* current = decl->AsVariableDeclaration()->AsNested()->scope();
1276 DCHECK(decl->var()->mode() == VariableMode::kVar ||((void) 0)
1277 decl->var()->mode() == VariableMode::kDynamic)((void) 0);
1278 // Iterate through all scopes until the declaration scope.
1279 do {
1280 // There is a conflict if there exists a non-VAR binding.
1281 Variable* other_var = current->LookupLocal(decl->var()->raw_name());
1282 if (current->is_catch_scope()) {
1283 *allowed_catch_binding_var_redeclaration |= other_var != nullptr;
1284 current = current->outer_scope();
1285 continue;
1286 }
1287 if (other_var != nullptr) {
1288 DCHECK(IsLexicalVariableMode(other_var->mode()))((void) 0);
1289 return decl;
1290 }
1291 current = current->outer_scope();
1292 } while (current != this);
1293 }
1294 }
1295
1296 if (V8_LIKELY(!is_eval_scope())(__builtin_expect(!!(!is_eval_scope()), 1))) return nullptr;
1297 if (!is_sloppy(language_mode())) return nullptr;
1298
1299 // Var declarations in sloppy eval are hoisted to the first non-eval
1300 // declaration scope. Check for conflicts between the eval scope that
1301 // declaration scope.
1302 Scope* end = outer_scope()->GetNonEvalDeclarationScope()->outer_scope();
1303
1304 for (Declaration* decl : decls_) {
1305 if (IsLexicalVariableMode(decl->var()->mode())) continue;
1306 Scope* current = outer_scope_;
1307 // Iterate through all scopes until and including the declaration scope.
1308 do {
1309 // There is a conflict if there exists a non-VAR binding up to the
1310 // declaration scope in which this sloppy-eval runs.
1311 //
1312 // Use the current scope as the cache, since the general cache would be
1313 // the end scope.
1314 Variable* other_var =
1315 current->LookupInScopeOrScopeInfo(decl->var()->raw_name(), current);
1316 if (other_var != nullptr && !current->is_catch_scope()) {
1317 // If this is a VAR, then we know that it doesn't conflict with
1318 // anything, so we can't conflict with anything either. The one
1319 // exception is the binding variable in catch scopes, which is handled
1320 // by the if above.
1321 if (!IsLexicalVariableMode(other_var->mode())) break;
1322 return decl;
1323 }
1324 current = current->outer_scope();
1325 } while (current != end);
1326 }
1327 return nullptr;
1328}
1329
1330const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope,
1331 VariableMode mode_limit) {
1332 const VariableMap& variables = scope->variables_;
1333 for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr;
1334 p = variables.Next(p)) {
1335 const AstRawString* name = static_cast<const AstRawString*>(p->key);
1336 Variable* var = LookupLocal(name);
1337 if (var != nullptr && var->mode() <= mode_limit) return name;
1338 }
1339 return nullptr;
1340}
1341
1342void DeclarationScope::DeserializeReceiver(AstValueFactory* ast_value_factory) {
1343 if (is_script_scope()) {
1344 DCHECK_NOT_NULL(receiver_)((void) 0);
1345 return;
1346 }
1347 DCHECK(has_this_declaration())((void) 0);
1348 DeclareThis(ast_value_factory);
1349 if (is_debug_evaluate_scope()) {
1350 receiver_->AllocateTo(VariableLocation::LOOKUP, -1);
1351 } else {
1352 receiver_->AllocateTo(VariableLocation::CONTEXT,
1353 scope_info_->ReceiverContextSlotIndex());
1354 }
1355}
1356
1357bool DeclarationScope::AllocateVariables(ParseInfo* info) {
1358 // Module variables must be allocated before variable resolution
1359 // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1360 if (is_module_scope()) AsModuleScope()->AllocateModuleVariables();
1361
1362 PrivateNameScopeIterator private_name_scope_iter(this);
1363 if (!private_name_scope_iter.Done() &&
1364 !private_name_scope_iter.GetScope()->ResolvePrivateNames(info)) {
1365 DCHECK(info->pending_error_handler()->has_pending_error())((void) 0);
1366 return false;
1367 }
1368
1369 if (!ResolveVariablesRecursively(info->scope())) {
1370 DCHECK(info->pending_error_handler()->has_pending_error())((void) 0);
1371 return false;
1372 }
1373
1374 // Don't allocate variables of preparsed scopes.
1375 if (!was_lazily_parsed()) AllocateVariablesRecursively();
1376
1377 return true;
1378}
1379
1380bool Scope::HasThisReference() const {
1381 if (is_declaration_scope() && AsDeclarationScope()->has_this_reference()) {
1382 return true;
1383 }
1384
1385 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1386 if (!scope->is_declaration_scope() ||
1387 !scope->AsDeclarationScope()->has_this_declaration()) {
1388 if (scope->HasThisReference()) return true;
1389 }
1390 }
1391
1392 return false;
1393}
1394
1395bool Scope::AllowsLazyParsingWithoutUnresolvedVariables(
1396 const Scope* outer) const {
1397 // If none of the outer scopes need to decide whether to context allocate
1398 // specific variables, we can preparse inner functions without unresolved
1399 // variables. Otherwise we need to find unresolved variables to force context
1400 // allocation of the matching declarations. We can stop at the outer scope for
1401 // the parse, since context allocation of those variables is already
1402 // guaranteed to be correct.
1403 for (const Scope* s = this; s != outer; s = s->outer_scope_) {
1404 // Eval forces context allocation on all outer scopes, so we don't need to
1405 // look at those scopes. Sloppy eval makes top-level non-lexical variables
1406 // dynamic, whereas strict-mode requires context allocation.
1407 if (s->is_eval_scope()) return is_sloppy(s->language_mode());
1408 // Catch scopes force context allocation of all variables.
1409 if (s->is_catch_scope()) continue;
1410 // With scopes do not introduce variables that need allocation.
1411 if (s->is_with_scope()) continue;
1412 DCHECK(s->is_module_scope() || s->is_block_scope() ||((void) 0)
1413 s->is_function_scope())((void) 0);
1414 return false;
1415 }
1416 return true;
1417}
1418
1419bool DeclarationScope::AllowsLazyCompilation() const {
1420 // Functions which force eager compilation and class member initializer
1421 // functions are not lazily compilable.
1422 return !force_eager_compilation_ &&
1423 !IsClassMembersInitializerFunction(function_kind());
1424}
1425
1426int Scope::ContextChainLength(Scope* scope) const {
1427 int n = 0;
1428 for (const Scope* s = this; s != scope; s = s->outer_scope_) {
1429 DCHECK_NOT_NULL(s)((void) 0); // scope must be in the scope chain
1430 if (s->NeedsContext()) n++;
1431 }
1432 return n;
1433}
1434
1435int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
1436 int result = 0;
1437 int length = 0;
1438
1439 for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
1440 if (!s->NeedsContext()) continue;
1441 length++;
1442 if (s->is_declaration_scope() &&
1443 s->AsDeclarationScope()->sloppy_eval_can_extend_vars()) {
1444 result = length;
1445 }
1446 }
1447
1448 return result;
1449}
1450
1451DeclarationScope* Scope::GetDeclarationScope() {
1452 Scope* scope = this;
1453 while (!scope->is_declaration_scope()) {
1454 scope = scope->outer_scope();
1455 }
1456 return scope->AsDeclarationScope();
1457}
1458
1459DeclarationScope* Scope::GetNonEvalDeclarationScope() {
1460 Scope* scope = this;
1461 while (!scope->is_declaration_scope() || scope->is_eval_scope()) {
1462 scope = scope->outer_scope();
1463 }
1464 return scope->AsDeclarationScope();
1465}
1466
1467const DeclarationScope* Scope::GetClosureScope() const {
1468 const Scope* scope = this;
1469 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1470 scope = scope->outer_scope();
1471 }
1472 return scope->AsDeclarationScope();
1473}
1474
1475DeclarationScope* Scope::GetClosureScope() {
1476 Scope* scope = this;
1477 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
1478 scope = scope->outer_scope();
1479 }
1480 return scope->AsDeclarationScope();
1481}
1482
1483bool Scope::NeedsScopeInfo() const {
1484 DCHECK(!already_resolved_)((void) 0);
1485 DCHECK(GetClosureScope()->ShouldEagerCompile())((void) 0);
1486 // The debugger expects all functions to have scope infos.
1487 // TODO(yangguo): Remove this requirement.
1488 if (is_function_scope()) return true;
1489 return NeedsContext();
1490}
1491
1492bool Scope::ShouldBanArguments() {
1493 return GetReceiverScope()->should_ban_arguments();
1494}
1495
1496DeclarationScope* Scope::GetReceiverScope() {
1497 Scope* scope = this;
1498 while (!scope->is_declaration_scope() ||
1499 (!scope->is_script_scope() &&
1500 !scope->AsDeclarationScope()->has_this_declaration())) {
1501 scope = scope->outer_scope();
1502 }
1503 return scope->AsDeclarationScope();
1504}
1505
1506DeclarationScope* Scope::GetConstructorScope() {
1507 Scope* scope = this;
1508 while (scope != nullptr && !scope->IsConstructorScope()) {
1509 scope = scope->outer_scope();
1510 }
1511 if (scope == nullptr) {
1512 return nullptr;
1513 }
1514 DCHECK(scope->IsConstructorScope())((void) 0);
1515 return scope->AsDeclarationScope();
1516}
1517
1518Scope* Scope::GetHomeObjectScope() {
1519 Scope* scope = this;
1520 while (scope != nullptr && !scope->is_home_object_scope()) {
1521 if (scope->is_function_scope()) {
1522 FunctionKind function_kind = scope->AsDeclarationScope()->function_kind();
1523 // "super" in arrow functions binds outside the arrow function. But if we
1524 // find a function which doesn't bind "super" (is not a method etc.) and
1525 // not an arrow function, we know "super" here doesn't bind anywhere and
1526 // we can return nullptr.
1527 if (!IsArrowFunction(function_kind) && !BindsSuper(function_kind)) {
1528 return nullptr;
1529 }
1530 }
1531 if (scope->private_name_lookup_skips_outer_class()) {
1532 DCHECK(scope->outer_scope()->is_class_scope())((void) 0);
1533 scope = scope->outer_scope()->outer_scope();
1534 } else {
1535 scope = scope->outer_scope();
1536 }
1537 }
1538 return scope;
1539}
1540
1541DeclarationScope* Scope::GetScriptScope() {
1542 Scope* scope = this;
1543 while (!scope->is_script_scope()) {
1544 scope = scope->outer_scope();
1545 }
1546 return scope->AsDeclarationScope();
1547}
1548
1549Scope* Scope::GetOuterScopeWithContext() {
1550 Scope* scope = outer_scope_;
1551 while (scope && !scope->NeedsContext()) {
1552 scope = scope->outer_scope();
1553 }
1554 return scope;
1555}
1556
1557namespace {
1558bool WasLazilyParsed(Scope* scope) {
1559 return scope->is_declaration_scope() &&
1560 scope->AsDeclarationScope()->was_lazily_parsed();
1561}
1562
1563} // namespace
1564
1565template <typename FunctionType>
1566void Scope::ForEach(FunctionType callback) {
1567 Scope* scope = this;
1568 while (true) {
3
Loop condition is true. Entering loop body
6
Loop condition is true. Entering loop body
1569 Iteration iteration = callback(scope);
7
Calling 'operator()'
1570 // Try to descend into inner scopes first.
1571 if ((iteration
3.1
'iteration' is equal to kDescend
== Iteration::kDescend) && scope->inner_scope_ != nullptr) {
4
Assuming the condition is true
5
Taking true branch
1572 scope = scope->inner_scope_;
1573 } else {
1574 // Find the next outer scope with a sibling.
1575 while (scope->sibling_ == nullptr) {
1576 if (scope == this) return;
1577 scope = scope->outer_scope_;
1578 }
1579 if (scope == this) return;
1580 scope = scope->sibling_;
1581 }
1582 }
1583}
1584
1585bool Scope::IsConstructorScope() const {
1586 return is_declaration_scope() &&
1587 IsClassConstructor(AsDeclarationScope()->function_kind());
1588}
1589
1590bool Scope::IsOuterScopeOf(Scope* other) const {
1591 Scope* scope = other;
1592 while (scope) {
1593 if (scope == this) return true;
1594 scope = scope->outer_scope();
1595 }
1596 return false;
1597}
1598
1599void Scope::CollectNonLocals(DeclarationScope* max_outer_scope,
1600 Isolate* isolate, Handle<StringSet>* non_locals) {
1601 this->ForEach([max_outer_scope, isolate, non_locals](Scope* scope) {
1602 // Module variables must be allocated before variable resolution
1603 // to ensure that UpdateNeedsHoleCheck() can detect import variables.
1604 if (scope->is_module_scope()) {
1605 scope->AsModuleScope()->AllocateModuleVariables();
1606 }
1607
1608 // Lazy parsed declaration scopes are already partially analyzed. If there
1609 // are unresolved references remaining, they just need to be resolved in
1610 // outer scopes.
1611 Scope* lookup = WasLazilyParsed(scope) ? scope->outer_scope() : scope;
1612
1613 for (VariableProxy* proxy : scope->unresolved_list_) {
1614 DCHECK(!proxy->is_resolved())((void) 0);
1615 Variable* var =
1616 Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope());
1617 if (var == nullptr) {
1618 *non_locals = StringSet::Add(isolate, *non_locals, proxy->name());
1619 } else {
1620 // In this case we need to leave scopes in a way that they can be
1621 // allocated. If we resolved variables from lazy parsed scopes, we need
1622 // to context allocate the var.
1623 scope->ResolveTo(proxy, var);
1624 if (!var->is_dynamic() && lookup != scope)
1625 var->ForceContextAllocation();
1626 }
1627 }
1628
1629 // Clear unresolved_list_ as it's in an inconsistent state.
1630 scope->unresolved_list_.Clear();
1631 return Iteration::kDescend;
1632 });
1633}
1634
1635void Scope::AnalyzePartially(DeclarationScope* max_outer_scope,
1636 AstNodeFactory* ast_node_factory,
1637 UnresolvedList* new_unresolved_list,
1638 bool maybe_in_arrowhead) {
1639 this->ForEach([max_outer_scope, ast_node_factory, new_unresolved_list,
2
Calling 'Scope::ForEach'
1640 maybe_in_arrowhead](Scope* scope) {
1641 DCHECK_IMPLIES(scope->is_declaration_scope(),((void) 0)
1642 !scope->AsDeclarationScope()->was_lazily_parsed())((void) 0);
1643
1644 for (VariableProxy* proxy = scope->unresolved_list_.first();
9
Loop condition is true. Entering loop body
1645 proxy != nullptr; proxy = proxy->next_unresolved()) {
8
Assuming the condition is true
1646 if (proxy->is_removed_from_unresolved()) continue;
10
Assuming the condition is false
11
Taking false branch
1647 DCHECK(!proxy->is_resolved())((void) 0);
1648 Variable* var =
1649 Lookup<kParsedScope>(proxy, scope, max_outer_scope->outer_scope());
12
Passing null pointer value via 4th parameter 'cache_scope'
13
Calling 'Scope::Lookup'
1650 if (var == nullptr) {
1651 // Don't copy unresolved references to the script scope, unless it's a
1652 // reference to a private name or method. In that case keep it so we
1653 // can fail later.
1654 if (!max_outer_scope->outer_scope()->is_script_scope() ||
1655 maybe_in_arrowhead) {
1656 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
1657 new_unresolved_list->Add(copy);
1658 }
1659 } else {
1660 var->set_is_used();
1661 if (proxy->is_assigned()) var->SetMaybeAssigned();
1662 }
1663 }
1664
1665 // Clear unresolved_list_ as it's in an inconsistent state.
1666 scope->unresolved_list_.Clear();
1667 return Iteration::kDescend;
1668 });
1669}
1670
1671Handle<StringSet> DeclarationScope::CollectNonLocals(
1672 Isolate* isolate, Handle<StringSet> non_locals) {
1673 Scope::CollectNonLocals(this, isolate, &non_locals);
1674 return non_locals;
1675}
1676
1677void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
1678 bool aborted) {
1679 DCHECK(is_function_scope())((void) 0);
1680
1681 // Reset all non-trivial members.
1682 params_.DropAndClear();
1683 decls_.Clear();
1684 locals_.Clear();
1685 inner_scope_ = nullptr;
1686 unresolved_list_.Clear();
1687 sloppy_block_functions_.Clear();
1688 rare_data_ = nullptr;
1689 has_rest_ = false;
1690 function_ = nullptr;
1691
1692 DCHECK_NE(zone(), ast_value_factory->single_parse_zone())((void) 0);
1693 // Make sure this scope and zone aren't used for allocation anymore.
1694 {
1695 // Get the zone, while variables_ is still valid
1696 Zone* zone = this->zone();
1697 variables_.Invalidate();
1698 zone->Reset();
1699 }
1700
1701 if (aborted) {
1702 // Prepare scope for use in the outer zone.
1703 variables_ = VariableMap(ast_value_factory->single_parse_zone());
1704 if (!IsArrowFunction(function_kind_)) {
1705 has_simple_parameters_ = true;
1706 DeclareDefaultFunctionVariables(ast_value_factory);
1707 }
1708 }
1709
1710#ifdef DEBUG
1711 needs_migration_ = false;
1712 is_being_lazily_parsed_ = false;
1713#endif
1714
1715 was_lazily_parsed_ = !aborted;
1716}
1717
1718bool Scope::IsSkippableFunctionScope() {
1719 // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
1720 // those Scopes which have their own PreparseDataBuilder object. This
1721 // logic ensures that the scope allocation data is consistent with the
1722 // skippable function data (both agree on where the lazy function boundaries
1723 // are).
1724 if (!is_function_scope()) return false;
1725 DeclarationScope* declaration_scope = AsDeclarationScope();
1726 return !declaration_scope->is_arrow_scope() &&
1727 declaration_scope->preparse_data_builder() != nullptr;
1728}
1729
1730void Scope::SavePreparseData(Parser* parser) {
1731 this->ForEach([parser](Scope* scope) {
1732 if (scope->IsSkippableFunctionScope()) {
1733 scope->AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser);
1734 }
1735 return Iteration::kDescend;
1736 });
1737}
1738
1739void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) {
1740 if (preparse_data_builder_ == nullptr) return;
1741 preparse_data_builder_->SaveScopeAllocationData(this, parser);
1742}
1743
1744void DeclarationScope::AnalyzePartially(Parser* parser,
1745 AstNodeFactory* ast_node_factory,
1746 bool maybe_in_arrowhead) {
1747 DCHECK(!force_eager_compilation_)((void) 0);
1748 UnresolvedList new_unresolved_list;
1749 if (!IsArrowFunction(function_kind_) &&
1750 (!outer_scope_->is_script_scope() || maybe_in_arrowhead ||
1751 (preparse_data_builder_ != nullptr &&
1752 preparse_data_builder_->HasInnerFunctions()))) {
1753 // Try to resolve unresolved variables for this Scope and migrate those
1754 // which cannot be resolved inside. It doesn't make sense to try to resolve
1755 // them in the outer Scopes here, because they are incomplete.
1756 Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list,
1
Calling 'Scope::AnalyzePartially'
1757 maybe_in_arrowhead);
1758
1759 // Migrate function_ to the right Zone.
1760 if (function_ != nullptr) {
1761 function_ = ast_node_factory->CopyVariable(function_);
1762 }
1763
1764 SavePreparseData(parser);
1765 }
1766
1767#ifdef DEBUG
1768 if (FLAG_print_scopes) {
1769 PrintF("Inner function scope:\n");
1770 Print();
1771 }
1772#endif
1773
1774 ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false);
1775
1776 unresolved_list_ = std::move(new_unresolved_list);
1777}
1778
1779void DeclarationScope::RewriteReplGlobalVariables() {
1780 DCHECK(is_script_scope())((void) 0);
1781 if (!is_repl_mode_scope()) return;
1782
1783 for (VariableMap::Entry* p = variables_.Start(); p != nullptr;
1784 p = variables_.Next(p)) {
1785 Variable* var = reinterpret_cast<Variable*>(p->value);
1786 var->RewriteLocationForRepl();
1787 }
1788}
1789
1790#ifdef DEBUG
1791namespace {
1792
1793const char* Header(ScopeType scope_type, FunctionKind function_kind,
1794 bool is_declaration_scope) {
1795 switch (scope_type) {
1796 case EVAL_SCOPE: return "eval";
1797 case FUNCTION_SCOPE:
1798 if (IsGeneratorFunction(function_kind)) return "function*";
1799 if (IsAsyncFunction(function_kind)) return "async function";
1800 if (IsArrowFunction(function_kind)) return "arrow";
1801 return "function";
1802 case MODULE_SCOPE: return "module";
1803 case SCRIPT_SCOPE: return "global";
1804 case CATCH_SCOPE: return "catch";
1805 case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block";
1806 case CLASS_SCOPE:
1807 return "class";
1808 case WITH_SCOPE: return "with";
1809 }
1810 UNREACHABLE()V8_Fatal("unreachable code");
1811}
1812
1813void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); }
1814
1815void PrintName(const AstRawString* name) {
1816 PrintF("%.*s", name->length(), name->raw_data());
1817}
1818
1819void PrintLocation(Variable* var) {
1820 switch (var->location()) {
1821 case VariableLocation::UNALLOCATED:
1822 break;
1823 case VariableLocation::PARAMETER:
1824 PrintF("parameter[%d]", var->index());
1825 break;
1826 case VariableLocation::LOCAL:
1827 PrintF("local[%d]", var->index());
1828 break;
1829 case VariableLocation::CONTEXT:
1830 PrintF("context[%d]", var->index());
1831 break;
1832 case VariableLocation::LOOKUP:
1833 PrintF("lookup");
1834 break;
1835 case VariableLocation::MODULE:
1836 PrintF("module");
1837 break;
1838 case VariableLocation::REPL_GLOBAL:
1839 PrintF("repl global[%d]", var->index());
1840 break;
1841 }
1842}
1843
1844void PrintVar(int indent, Variable* var) {
1845 Indent(indent, VariableMode2String(var->mode()));
1846 PrintF(" ");
1847 if (var->raw_name()->IsEmpty())
1848 PrintF(".%p", reinterpret_cast<void*>(var));
1849 else
1850 PrintName(var->raw_name());
1851 PrintF("; // (%p) ", reinterpret_cast<void*>(var));
1852 PrintLocation(var);
1853 bool comma = !var->IsUnallocated();
1854 if (var->has_forced_context_allocation()) {
1855 if (comma) PrintF(", ");
1856 PrintF("forced context allocation");
1857 comma = true;
1858 }
1859 if (var->maybe_assigned() == kNotAssigned) {
1860 if (comma) PrintF(", ");
1861 PrintF("never assigned");
1862 comma = true;
1863 }
1864 if (var->initialization_flag() == kNeedsInitialization &&
1865 !var->binding_needs_init()) {
1866 if (comma) PrintF(", ");
1867 PrintF("hole initialization elided");
1868 }
1869 PrintF("\n");
1870}
1871
1872void PrintMap(int indent, const char* label, VariableMap* map, bool locals,
1873 Variable* function_var) {
1874 bool printed_label = false;
1875 for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
1876 Variable* var = reinterpret_cast<Variable*>(p->value);
1877 if (var == function_var) continue;
1878 bool local = !IsDynamicVariableMode(var->mode());
1879 if ((locals ? local : !local) &&
1880 (var->is_used() || !var->IsUnallocated())) {
1881 if (!printed_label) {
1882 Indent(indent, label);
1883 printed_label = true;
1884 }
1885 PrintVar(indent, var);
1886 }
1887 }
1888}
1889
1890} // anonymous namespace
1891
1892void DeclarationScope::PrintParameters() {
1893 PrintF(" (");
1894 for (int i = 0; i < params_.length(); i++) {
1895 if (i > 0) PrintF(", ");
1896 const AstRawString* name = params_[i]->raw_name();
1897 if (name->IsEmpty()) {
1898 PrintF(".%p", reinterpret_cast<void*>(params_[i]));
1899 } else {
1900 PrintName(name);
1901 }
1902 }
1903 PrintF(")");
1904}
1905
1906void Scope::Print(int n) {
1907 int n0 = (n > 0 ? n : 0);
1908 int n1 = n0 + 2; // indentation
1909
1910 // Print header.
1911 FunctionKind function_kind = is_function_scope()
1912 ? AsDeclarationScope()->function_kind()
1913 : FunctionKind::kNormalFunction;
1914 Indent(n0, Header(scope_type_, function_kind, is_declaration_scope()));
1915 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) {
1916 PrintF(" ");
1917 PrintName(scope_name_);
1918 }
1919
1920 // Print parameters, if any.
1921 Variable* function = nullptr;
1922 if (is_function_scope()) {
1923 AsDeclarationScope()->PrintParameters();
1924 function = AsDeclarationScope()->function_var();
1925 }
1926
1927 PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this),
1928 start_position(), end_position());
1929 if (is_hidden()) {
1930 Indent(n1, "// is hidden\n");
1931 }
1932
1933 // Function name, if any (named function literals, only).
1934 if (function != nullptr) {
1935 Indent(n1, "// (local) function name: ");
1936 PrintName(function->raw_name());
1937 PrintF("\n");
1938 }
1939
1940 // Scope info.
1941 if (is_strict(language_mode())) {
1942 Indent(n1, "// strict mode scope\n");
1943 }
1944#if V8_ENABLE_WEBASSEMBLY1
1945 if (IsAsmModule()) Indent(n1, "// scope is an asm module\n");
1946#endif // V8_ENABLE_WEBASSEMBLY
1947 if (is_declaration_scope() &&
1948 AsDeclarationScope()->sloppy_eval_can_extend_vars()) {
1949 Indent(n1, "// scope calls sloppy 'eval'\n");
1950 }
1951 if (private_name_lookup_skips_outer_class()) {
1952 Indent(n1, "// scope skips outer class for #-names\n");
1953 }
1954 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
1955 if (is_declaration_scope()) {
1956 DeclarationScope* scope = AsDeclarationScope();
1957 if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n");
1958 if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n");
1959 if (scope->needs_private_name_context_chain_recalc()) {
1960 Indent(n1, "// needs #-name context chain recalc\n");
1961 }
1962 Indent(n1, "// ");
1963 PrintF("%s\n", FunctionKind2String(scope->function_kind()));
1964 if (scope->class_scope_has_private_brand()) {
1965 Indent(n1, "// class scope has private brand\n");
1966 }
1967 }
1968 if (num_stack_slots_ > 0) {
1969 Indent(n1, "// ");
1970 PrintF("%d stack slots\n", num_stack_slots_);
1971 }
1972 if (num_heap_slots_ > 0) {
1973 Indent(n1, "// ");
1974 PrintF("%d heap slots\n", num_heap_slots_);
1975 }
1976
1977 // Print locals.
1978 if (function != nullptr) {
1979 Indent(n1, "// function var:\n");
1980 PrintVar(n1, function);
1981 }
1982
1983 // Print temporaries.
1984 {
1985 bool printed_header = false;
1986 for (Variable* local : locals_) {
1987 if (local->mode() != VariableMode::kTemporary) continue;
1988 if (!printed_header) {
1989 printed_header = true;
1990 Indent(n1, "// temporary vars:\n");
1991 }
1992 PrintVar(n1, local);
1993 }
1994 }
1995
1996 if (variables_.occupancy() > 0) {
1997 PrintMap(n1, "// local vars:\n", &variables_, true, function);
1998 PrintMap(n1, "// dynamic vars:\n", &variables_, false, function);
1999 }
2000
2001 if (is_class_scope()) {
2002 ClassScope* class_scope = AsClassScope();
2003 if (class_scope->GetRareData() != nullptr) {
2004 PrintMap(n1, "// private name vars:\n",
2005 &(class_scope->GetRareData()->private_name_map), true, function);
2006 Variable* brand = class_scope->brand();
2007 if (brand != nullptr) {
2008 Indent(n1, "// brand var:\n");
2009 PrintVar(n1, brand);
2010 }
2011 }
2012 if (class_scope->class_variable() != nullptr) {
2013 Indent(n1, "// class var");
2014 PrintF("%s%s:\n",
2015 class_scope->class_variable()->is_used() ? ", used" : ", unused",
2016 class_scope->should_save_class_variable_index()
2017 ? ", index saved"
2018 : ", index not saved");
2019 PrintVar(n1, class_scope->class_variable());
2020 }
2021 }
2022
2023 // Print inner scopes (disable by providing negative n).
2024 if (n >= 0) {
2025 for (Scope* scope = inner_scope_; scope != nullptr;
2026 scope = scope->sibling_) {
2027 PrintF("\n");
2028 scope->Print(n1);
2029 }
2030 }
2031
2032 Indent(n0, "}\n");
2033}
2034
2035void Scope::CheckScopePositions() {
2036 this->ForEach([](Scope* scope) {
2037 // Visible leaf scopes must have real positions.
2038 if (!scope->is_hidden() && scope->inner_scope_ == nullptr) {
2039 DCHECK_NE(kNoSourcePosition, scope->start_position())((void) 0);
2040 DCHECK_NE(kNoSourcePosition, scope->end_position())((void) 0);
2041 }
2042 return Iteration::kDescend;
2043 });
2044}
2045
2046void Scope::CheckZones() {
2047 DCHECK(!needs_migration_)((void) 0);
2048 this->ForEach([](Scope* scope) {
2049 if (WasLazilyParsed(scope)) {
2050 DCHECK_NULL(scope->zone())((void) 0);
2051 DCHECK_NULL(scope->inner_scope_)((void) 0);
2052 return Iteration::kContinue;
2053 }
2054 return Iteration::kDescend;
2055 });
2056}
2057#endif // DEBUG
2058
2059Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
2060 // Declare a new non-local.
2061 DCHECK(IsDynamicVariableMode(mode))((void) 0);
2062 bool was_added;
2063 Variable* var = variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE,
2064 kCreatedInitialized, kNotAssigned,
2065 IsStaticFlag::kNotStatic, &was_added);
2066 // Allocate it by giving it a dynamic lookup.
2067 var->AllocateTo(VariableLocation::LOOKUP, -1);
2068 return var;
2069}
2070
2071// static
2072template <Scope::ScopeLookupMode mode>
2073Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
2074 Scope* outer_scope_end, Scope* cache_scope,
2075 bool force_context_allocation) {
2076 // If we have already passed the cache scope in earlier recursions, we should
2077 // first quickly check if the current scope uses the cache scope before
2078 // continuing.
2079 if (mode
13.1
0 is not equal to kDeserializedScope
== kDeserializedScope &&
2080 scope->deserialized_scope_uses_external_cache()) {
2081 Variable* var = cache_scope->variables_.Lookup(proxy->raw_name());
2082 if (var != nullptr) return var;
2083 }
2084
2085 while (true) {
14
Loop condition is true. Entering loop body
2086 DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_)((void) 0);
2087 // Short-cut: whenever we find a debug-evaluate scope, just look everything
2088 // up dynamically. Debug-evaluate doesn't properly create scope info for the
2089 // lookups it does. It may not have a valid 'this' declaration, and anything
2090 // accessed through debug-evaluate might invalidly resolve to
2091 // stack-allocated variables.
2092 // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for
2093 // the scopes in which it's evaluating.
2094 if (mode
14.1
0 is not equal to kDeserializedScope
== kDeserializedScope &&
2095 V8_UNLIKELY(scope->is_debug_evaluate_scope_)(__builtin_expect(!!(scope->is_debug_evaluate_scope_), 0))) {
2096 DCHECK(scope->deserialized_scope_uses_external_cache() ||((void) 0)
2097 scope == cache_scope)((void) 0);
2098 return cache_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
2099 }
2100
2101 // Try to find the variable in this scope.
2102 Variable* var;
2103 if (mode
14.2
0 is equal to kParsedScope
== kParsedScope) {
15
Taking true branch
2104 var = scope->LookupLocal(proxy->raw_name());
2105 } else {
2106 DCHECK_EQ(mode, kDeserializedScope)((void) 0);
2107 bool external_cache = scope->deserialized_scope_uses_external_cache();
2108 if (!external_cache) {
2109 // Check the cache on each deserialized scope, up to the main cache
2110 // scope when we get to it (we may still have deserialized scopes
2111 // in-between the initial and cache scopes so we can't just check the
2112 // cache before the loop).
2113 var = scope->variables_.Lookup(proxy->raw_name());
2114 if (var != nullptr) return var;
2115 }
2116 var = scope->LookupInScopeInfo(proxy->raw_name(),
2117 external_cache ? cache_scope : scope);
2118 }
2119
2120 // We found a variable and we are done. (Even if there is an 'eval' in this
2121 // scope which introduces the same variable again, the resulting variable
2122 // remains the same.)
2123 //
2124 // For sloppy eval though, we skip dynamic variable to avoid resolving to a
2125 // variable when the variable and proxy are in the same eval execution. The
2126 // variable is not available on subsequent lazy executions of functions in
2127 // the eval, so this avoids inner functions from looking up different
2128 // variables during eager and lazy compilation.
2129 //
2130 // TODO(leszeks): Maybe we want to restrict this to e.g. lookups of a proxy
2131 // living in a different scope to the current one, or some other
2132 // optimisation.
2133 if (var != nullptr &&
2134 !(scope->is_eval_scope() && var->mode() == VariableMode::kDynamic)) {
2135 if (mode == kParsedScope && force_context_allocation &&
2136 !var->is_dynamic()) {
2137 var->ForceContextAllocation();
2138 }
2139 return var;
2140 }
2141
2142 if (scope->outer_scope_ == outer_scope_end) break;
16
Assuming 'outer_scope_end' is not equal to field 'outer_scope_'
17
Taking false branch
2143
2144 DCHECK(!scope->is_script_scope())((void) 0);
2145 if (V8_UNLIKELY(scope->is_with_scope())(__builtin_expect(!!(scope->is_with_scope()), 0))) {
18
Taking true branch
2146 return LookupWith(proxy, scope, outer_scope_end, cache_scope,
19
Passing null pointer value via 4th parameter 'cache_scope'
20
Calling 'Scope::LookupWith'
2147 force_context_allocation);
2148 }
2149 if (V8_UNLIKELY((__builtin_expect(!!(scope->is_declaration_scope() &&
scope->AsDeclarationScope()->sloppy_eval_can_extend_vars
()), 0))
2150 scope->is_declaration_scope() &&(__builtin_expect(!!(scope->is_declaration_scope() &&
scope->AsDeclarationScope()->sloppy_eval_can_extend_vars
()), 0))
2151 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars())(__builtin_expect(!!(scope->is_declaration_scope() &&
scope->AsDeclarationScope()->sloppy_eval_can_extend_vars
()), 0))
) {
2152 return LookupSloppyEval(proxy, scope, outer_scope_end, cache_scope,
2153 force_context_allocation);
2154 }
2155
2156 force_context_allocation |= scope->is_function_scope();
2157 scope = scope->outer_scope_;
2158
2159 // TODO(verwaest): Separate through AnalyzePartially.
2160 if (mode == kParsedScope && !scope->scope_info_.is_null()) {
2161 DCHECK_NULL(cache_scope)((void) 0);
2162 cache_scope = scope->GetNonEvalDeclarationScope();
2163 return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end,
2164 cache_scope);
2165 }
2166 }
2167
2168 // We may just be trying to find all free variables. In that case, don't
2169 // declare them in the outer scope.
2170 // TODO(marja): Separate Lookup for preparsed scopes better.
2171 if (mode == kParsedScope && !scope->is_script_scope()) {
2172 return nullptr;
2173 }
2174
2175 // No binding has been found. Declare a variable on the global object.
2176 return scope->AsDeclarationScope()->DeclareDynamicGlobal(
2177 proxy->raw_name(), NORMAL_VARIABLE,
2178 mode == kDeserializedScope ? cache_scope : scope);
2179}
2180
2181template Variable* Scope::Lookup<Scope::kParsedScope>(
2182 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
2183 Scope* cache_scope, bool force_context_allocation);
2184template Variable* Scope::Lookup<Scope::kDeserializedScope>(
2185 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end,
2186 Scope* cache_scope, bool force_context_allocation);
2187
2188Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope,
2189 Scope* outer_scope_end, Scope* cache_scope,
2190 bool force_context_allocation) {
2191 DCHECK(scope->is_with_scope())((void) 0);
2192
2193 Variable* var =
2194 scope->outer_scope_->scope_info_.is_null()
21
'?' condition is false
2195 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
2196 nullptr, force_context_allocation)
2197 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
2198 outer_scope_end, cache_scope);
2199
2200 if (var == nullptr) return var;
22
Assuming the condition is false
2201
2202 // The current scope is a with scope, so the variable binding can not be
2203 // statically resolved. However, note that it was necessary to do a lookup
2204 // in the outer scope anyway, because if a binding exists in an outer
2205 // scope, the associated variable has to be marked as potentially being
2206 // accessed from inside of an inner with scope (the property may not be in
2207 // the 'with' object).
2208 if (!var->is_dynamic() && var->IsUnallocated()) {
23
Assuming the condition is false
2209 DCHECK(!scope->already_resolved_)((void) 0);
2210 var->set_is_used();
2211 var->ForceContextAllocation();
2212 if (proxy->is_assigned()) var->SetMaybeAssigned();
2213 }
2214 Scope* target_scope;
2215 if (scope->deserialized_scope_uses_external_cache()) {
24
Assuming the condition is true
25
Taking true branch
2216 DCHECK_NOT_NULL(cache_scope)((void) 0);
2217 cache_scope->variables_.Remove(var);
26
Called C++ object pointer is null
2218 target_scope = cache_scope;
2219 } else {
2220 target_scope = scope;
2221 }
2222 Variable* dynamic =
2223 target_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic);
2224 dynamic->set_local_if_not_shadowed(var);
2225 return dynamic;
2226}
2227
2228Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope,
2229 Scope* outer_scope_end, Scope* cache_scope,
2230 bool force_context_allocation) {
2231 DCHECK(scope->is_declaration_scope() &&((void) 0)
2232 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars())((void) 0);
2233
2234 // If we're compiling eval, it's possible that the outer scope is the first
2235 // ScopeInfo-backed scope. We use the next declaration scope as the cache for
2236 // this case, to avoid complexity around sloppy block function hoisting and
2237 // conflict detection through catch scopes in the eval.
2238 Scope* entry_cache = cache_scope == nullptr
2239 ? scope->outer_scope()->GetNonEvalDeclarationScope()
2240 : cache_scope;
2241 Variable* var =
2242 scope->outer_scope_->scope_info_.is_null()
2243 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end,
2244 nullptr, force_context_allocation)
2245 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_,
2246 outer_scope_end, entry_cache);
2247 if (var == nullptr) return var;
2248
2249 // We may not want to use the cache scope, change it back to the given scope
2250 // if necessary.
2251 if (!scope->deserialized_scope_uses_external_cache()) {
2252 // For a deserialized scope, we'll be replacing the cache_scope.
2253 DCHECK_IMPLIES(!scope->scope_info_.is_null(), cache_scope != nullptr)((void) 0);
2254 cache_scope = scope;
2255 }
2256
2257 // A variable binding may have been found in an outer scope, but the current
2258 // scope makes a sloppy 'eval' call, so the found variable may not be the
2259 // correct one (the 'eval' may introduce a binding with the same name). In
2260 // that case, change the lookup result to reflect this situation. Only
2261 // scopes that can host var bindings (declaration scopes) need be considered
2262 // here (this excludes block and catch scopes), and variable lookups at
2263 // script scope are always dynamic.
2264 if (var->IsGlobalObjectProperty()) {
2265 Scope* target = cache_scope == nullptr ? scope : cache_scope;
2266 var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal);
2267 }
2268
2269 if (var->is_dynamic()) return var;
2270
2271 Variable* invalidated = var;
2272 if (cache_scope != nullptr) cache_scope->variables_.Remove(invalidated);
2273
2274 Scope* target = cache_scope == nullptr ? scope : cache_scope;
2275 var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal);
2276 var->set_local_if_not_shadowed(invalidated);
2277
2278 return var;
2279}
2280
2281void Scope::ResolveVariable(VariableProxy* proxy) {
2282 DCHECK(!proxy->is_resolved())((void) 0);
2283 Variable* var = Lookup<kParsedScope>(proxy, this, nullptr);
2284 DCHECK_NOT_NULL(var)((void) 0);
2285 ResolveTo(proxy, var);
2286}
2287
2288namespace {
2289
2290void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) {
2291 proxy->set_needs_hole_check();
2292 var->ForceHoleInitialization();
2293}
2294
2295void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) {
2296 if (var->mode() == VariableMode::kDynamicLocal) {
2297 // Dynamically introduced variables never need a hole check (since they're
2298 // VariableMode::kVar bindings, either from var or function declarations),
2299 // but the variable they shadow might need a hole check, which we want to do
2300 // if we decide that no shadowing variable was dynamically introoduced.
2301 DCHECK_EQ(kCreatedInitialized, var->initialization_flag())((void) 0);
2302 return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope);
2303 }
2304
2305 if (var->initialization_flag() == kCreatedInitialized) return;
2306
2307 // It's impossible to eliminate module import hole checks here, because it's
2308 // unknown at compilation time whether the binding referred to in the
2309 // exporting module itself requires hole checks.
2310 if (var->location() == VariableLocation::MODULE && !var->IsExport()) {
2311 return SetNeedsHoleCheck(var, proxy);
2312 }
2313
2314 // Check if the binding really needs an initialization check. The check
2315 // can be skipped in the following situation: we have a VariableMode::kLet or
2316 // VariableMode::kConst binding, both the Variable and the VariableProxy have
2317 // the same declaration scope (i.e. they are both in global code, in the same
2318 // function or in the same eval code), the VariableProxy is in the source
2319 // physically located after the initializer of the variable, and that the
2320 // initializer cannot be skipped due to a nonlinear scope.
2321 //
2322 // The condition on the closure scopes is a conservative check for
2323 // nested functions that access a binding and are called before the
2324 // binding is initialized:
2325 // function() { f(); let x = 1; function f() { x = 2; } }
2326 //
2327 // The check cannot be skipped on non-linear scopes, namely switch
2328 // scopes, to ensure tests are done in cases like the following:
2329 // switch (1) { case 0: let x = 2; case 1: f(x); }
2330 // The scope of the variable needs to be checked, in case the use is
2331 // in a sub-block which may be linear.
2332 if (var->scope()->GetClosureScope() != scope->GetClosureScope()) {
2333 return SetNeedsHoleCheck(var, proxy);
2334 }
2335
2336 // We should always have valid source positions.
2337 DCHECK_NE(var->initializer_position(), kNoSourcePosition)((void) 0);
2338 DCHECK_NE(proxy->position(), kNoSourcePosition)((void) 0);
2339
2340 if (var->scope()->is_nonlinear() ||
2341 var->initializer_position() >= proxy->position()) {
2342 return SetNeedsHoleCheck(var, proxy);
2343 }
2344}
2345
2346} // anonymous namespace
2347
2348void Scope::ResolveTo(VariableProxy* proxy, Variable* var) {
2349 DCHECK_NOT_NULL(var)((void) 0);
2350 UpdateNeedsHoleCheck(var, proxy, this);
2351 proxy->BindTo(var);
2352}
2353
2354void Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope,
2355 Scope* end) {
2356 // Resolve the variable in all parsed scopes to force context allocation.
2357 for (; scope != end; scope = scope->outer_scope_) {
2358 Variable* var = scope->LookupLocal(proxy->raw_name());
2359 if (var != nullptr) {
2360 var->set_is_used();
2361 if (!var->is_dynamic()) {
2362 var->ForceContextAllocation();
2363 if (proxy->is_assigned()) var->SetMaybeAssigned();
2364 return;
2365 }
2366 }
2367 }
2368}
2369
2370bool Scope::ResolveVariablesRecursively(Scope* end) {
2371 // Lazy parsed declaration scopes are already partially analyzed. If there are
2372 // unresolved references remaining, they just need to be resolved in outer
2373 // scopes.
2374 if (WasLazilyParsed(this)) {
2375 DCHECK_EQ(variables_.occupancy(), 0)((void) 0);
2376 // Resolve in all parsed scopes except for the script scope.
2377 if (!end->is_script_scope()) end = end->outer_scope();
2378
2379 for (VariableProxy* proxy : unresolved_list_) {
2380 ResolvePreparsedVariable(proxy, outer_scope(), end);
2381 }
2382 } else {
2383 // Resolve unresolved variables for this scope.
2384 for (VariableProxy* proxy : unresolved_list_) {
2385 ResolveVariable(proxy);
2386 }
2387
2388 // Resolve unresolved variables for inner scopes.
2389 for (Scope* scope = inner_scope_; scope != nullptr;
2390 scope = scope->sibling_) {
2391 if (!scope->ResolveVariablesRecursively(end)) return false;
2392 }
2393 }
2394 return true;
2395}
2396
2397bool Scope::MustAllocate(Variable* var) {
2398 DCHECK(var->location() != VariableLocation::MODULE)((void) 0);
2399 // Give var a read/write use if there is a chance it might be accessed
2400 // via an eval() call. This is only possible if the variable has a
2401 // visible name.
2402 if (!var->raw_name()->IsEmpty() &&
2403 (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) {
2404 var->set_is_used();
2405 if (inner_scope_calls_eval_ && !var->is_this()) var->SetMaybeAssigned();
2406 }
2407 DCHECK(!var->has_forced_context_allocation() || var->is_used())((void) 0);
2408 // Global variables do not need to be allocated.
2409 return !var->IsGlobalObjectProperty() && var->is_used();
2410}
2411
2412
2413bool Scope::MustAllocateInContext(Variable* var) {
2414 // If var is accessed from an inner scope, or if there is a possibility
2415 // that it might be accessed from the current or an inner scope (through
2416 // an eval() call or a runtime with lookup), it must be allocated in the
2417 // context.
2418 //
2419 // Temporary variables are always stack-allocated. Catch-bound variables are
2420 // always context-allocated.
2421 VariableMode mode = var->mode();
2422 if (mode == VariableMode::kTemporary) return false;
2423 if (is_catch_scope()) return true;
2424 if (is_script_scope() || is_eval_scope()) {
2425 if (IsLexicalVariableMode(mode)) {
2426 return true;
2427 }
2428 }
2429 return var->has_forced_context_allocation() || inner_scope_calls_eval_;
2430}
2431
2432void Scope::AllocateStackSlot(Variable* var) {
2433 if (is_block_scope()) {
2434 outer_scope()->GetDeclarationScope()->AllocateStackSlot(var);
2435 } else {
2436 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
2437 }
2438}
2439
2440
2441void Scope::AllocateHeapSlot(Variable* var) {
2442 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
2443}
2444
2445void DeclarationScope::AllocateParameterLocals() {
2446 DCHECK(is_function_scope())((void) 0);
2447
2448 bool has_mapped_arguments = false;
2449 if (arguments_ != nullptr) {
2450 DCHECK(!is_arrow_scope())((void) 0);
2451 if (MustAllocate(arguments_) && !has_arguments_parameter_) {
2452 // 'arguments' is used and does not refer to a function
2453 // parameter of the same name. If the arguments object
2454 // aliases formal parameters, we conservatively allocate
2455 // them specially in the loop below.
2456 has_mapped_arguments =
2457 GetArgumentsType() == CreateArgumentsType::kMappedArguments;
2458 } else {
2459 // 'arguments' is unused. Tell the code generator that it does not need to
2460 // allocate the arguments object by nulling out arguments_.
2461 arguments_ = nullptr;
2462 }
2463 }
2464
2465 // The same parameter may occur multiple times in the parameters_ list.
2466 // If it does, and if it is not copied into the context object, it must
2467 // receive the highest parameter index for that parameter; thus iteration
2468 // order is relevant!
2469 for (int i = num_parameters() - 1; i >= 0; --i) {
2470 Variable* var = params_[i];
2471 DCHECK_NOT_NULL(var)((void) 0);
2472 DCHECK(!has_rest_ || var != rest_parameter())((void) 0);
2473 DCHECK_EQ(this, var->scope())((void) 0);
2474 if (has_mapped_arguments) {
2475 var->set_is_used();
2476 var->SetMaybeAssigned();
2477 var->ForceContextAllocation();
2478 }
2479 AllocateParameter(var, i);
2480 }
2481}
2482
2483void DeclarationScope::AllocateParameter(Variable* var, int index) {
2484 if (!MustAllocate(var)) return;
2485 if (has_forced_context_allocation_for_parameters() ||
2486 MustAllocateInContext(var)) {
2487 DCHECK(var->IsUnallocated() || var->IsContextSlot())((void) 0);
2488 if (var->IsUnallocated()) AllocateHeapSlot(var);
2489 } else {
2490 DCHECK(var->IsUnallocated() || var->IsParameter())((void) 0);
2491 if (var->IsUnallocated()) {
2492 var->AllocateTo(VariableLocation::PARAMETER, index);
2493 }
2494 }
2495}
2496
2497void DeclarationScope::AllocateReceiver() {
2498 if (!has_this_declaration()) return;
2499 DCHECK_NOT_NULL(receiver())((void) 0);
2500 DCHECK_EQ(receiver()->scope(), this)((void) 0);
2501 AllocateParameter(receiver(), -1);
2502}
2503
2504void Scope::AllocateNonParameterLocal(Variable* var) {
2505 DCHECK_EQ(var->scope(), this)((void) 0);
2506 if (var->IsUnallocated() && MustAllocate(var)) {
2507 if (MustAllocateInContext(var)) {
2508 AllocateHeapSlot(var);
2509 DCHECK_IMPLIES(is_catch_scope(),((void) 0)
2510 var->index() == Context::THROWN_OBJECT_INDEX)((void) 0);
2511 } else {
2512 AllocateStackSlot(var);
2513 }
2514 }
2515}
2516
2517void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() {
2518 if (is_declaration_scope() && AsDeclarationScope()->is_arrow_scope()) {
2519 // In arrow functions, allocate non-temporaries first and then all the
2520 // temporaries to make the local variable ordering stable when reparsing to
2521 // collect source positions.
2522 for (Variable* local : locals_) {
2523 if (local->mode() != VariableMode::kTemporary)
2524 AllocateNonParameterLocal(local);
2525 }
2526
2527 for (Variable* local : locals_) {
2528 if (local->mode() == VariableMode::kTemporary)
2529 AllocateNonParameterLocal(local);
2530 }
2531 } else {
2532 for (Variable* local : locals_) {
2533 AllocateNonParameterLocal(local);
2534 }
2535 }
2536
2537 if (is_declaration_scope()) {
2538 AsDeclarationScope()->AllocateLocals();
2539 }
2540}
2541
2542void DeclarationScope::AllocateLocals() {
2543 // For now, function_ must be allocated at the very end. If it gets
2544 // allocated in the context, it must be the last slot in the context,
2545 // because of the current ScopeInfo implementation (see
2546 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
2547 if (function_ != nullptr && MustAllocate(function_)) {
2548 AllocateNonParameterLocal(function_);
2549 } else {
2550 function_ = nullptr;
2551 }
2552
2553 DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) ||((void) 0)
2554 !rest_parameter()->IsUnallocated())((void) 0);
2555
2556 if (new_target_ != nullptr && !MustAllocate(new_target_)) {
2557 new_target_ = nullptr;
2558 }
2559
2560 NullifyRareVariableIf(RareVariable::kThisFunction,
2561 [=](Variable* var) { return !MustAllocate(var); });
2562}
2563
2564void ModuleScope::AllocateModuleVariables() {
2565 for (const auto& it : module()->regular_imports()) {
2566 Variable* var = LookupLocal(it.first);
2567 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2568 DCHECK(!var->IsExport())((void) 0);
2569 }
2570
2571 for (const auto& it : module()->regular_exports()) {
2572 Variable* var = LookupLocal(it.first);
2573 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index);
2574 DCHECK(var->IsExport())((void) 0);
2575 }
2576}
2577
2578void Scope::AllocateVariablesRecursively() {
2579 this->ForEach([](Scope* scope) -> Iteration {
2580 DCHECK(!scope->already_resolved_)((void) 0);
2581 if (WasLazilyParsed(scope)) return Iteration::kContinue;
2582 DCHECK_EQ(scope->ContextHeaderLength(), scope->num_heap_slots_)((void) 0);
2583
2584 // Allocate variables for this scope.
2585 // Parameters must be allocated first, if any.
2586 if (scope->is_declaration_scope()) {
2587 scope->AsDeclarationScope()->AllocateReceiver();
2588 if (scope->is_function_scope()) {
2589 scope->AsDeclarationScope()->AllocateParameterLocals();
2590 }
2591 }
2592 scope->AllocateNonParameterLocalsAndDeclaredGlobals();
2593
2594 // Force allocation of a context for this scope if necessary. For a 'with'
2595 // scope and for a function scope that makes an 'eval' call we need a
2596 // context, even if no local variables were statically allocated in the
2597 // scope. Likewise for modules and function scopes representing asm.js
2598 // modules. Also force a context, if the scope is stricter than the outer
2599 // scope.
2600 bool must_have_context =
2601 scope->is_with_scope() || scope->is_module_scope() ||
2602#if V8_ENABLE_WEBASSEMBLY1
2603 scope->IsAsmModule() ||
2604#endif // V8_ENABLE_WEBASSEMBLY
2605 scope->ForceContextForLanguageMode() ||
2606 (scope->is_function_scope() &&
2607 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) ||
2608 (scope->is_block_scope() && scope->is_declaration_scope() &&
2609 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars());
2610
2611 // If we didn't allocate any locals in the local context, then we only
2612 // need the minimal number of slots if we must have a context.
2613 if (scope->num_heap_slots_ == scope->ContextHeaderLength() &&
2614 !must_have_context) {
2615 scope->num_heap_slots_ = 0;
2616 }
2617
2618 // Allocation done.
2619 DCHECK(scope->num_heap_slots_ == 0 ||((void) 0)
2620 scope->num_heap_slots_ >= scope->ContextHeaderLength())((void) 0);
2621 return Iteration::kDescend;
2622 });
2623}
2624
2625template <typename IsolateT>
2626void Scope::AllocateScopeInfosRecursively(IsolateT* isolate,
2627 MaybeHandle<ScopeInfo> outer_scope) {
2628 DCHECK(scope_info_.is_null())((void) 0);
2629 MaybeHandle<ScopeInfo> next_outer_scope = outer_scope;
2630
2631 if (NeedsScopeInfo()) {
2632 scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope);
2633 // The ScopeInfo chain should mirror the context chain, so we only link to
2634 // the next outer scope that needs a context.
2635 if (NeedsContext()) next_outer_scope = scope_info_;
2636 }
2637
2638 // Allocate ScopeInfos for inner scopes.
2639 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
2640 if (!scope->is_function_scope() ||
2641 scope->AsDeclarationScope()->ShouldEagerCompile()) {
2642 scope->AllocateScopeInfosRecursively(isolate, next_outer_scope);
2643 }
2644 }
2645}
2646
2647template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
2648 AllocateScopeInfosRecursively<Isolate>(Isolate* isolate,
2649 MaybeHandle<ScopeInfo> outer_scope);
2650template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope::
2651 AllocateScopeInfosRecursively<LocalIsolate>(
2652 LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
2653
2654void DeclarationScope::RecalcPrivateNameContextChain() {
2655 // The outermost scope in a class heritage expression is marked to skip the
2656 // class scope during private name resolution. It is possible, however, that
2657 // either the class scope won't require a Context and ScopeInfo, or the
2658 // outermost scope in the heritage position won't. Simply copying the bit from
2659 // full parse into the ScopeInfo will break lazy compilation. In the former
2660 // case the scope that is marked to skip its outer scope will incorrectly skip
2661 // a different class scope than the one we intended to skip. In the latter
2662 // case variables resolved through an inner scope will incorrectly check the
2663 // class scope since we lost the skip bit from the outermost heritage scope.
2664 //
2665 // This method fixes both cases by, in outermost to innermost order, copying
2666 // the value of the skip bit from outer scopes that don't require a Context.
2667 DCHECK(needs_private_name_context_chain_recalc_)((void) 0);
2668 this->ForEach([](Scope* scope) {
2669 Scope* outer = scope->outer_scope();
2670 if (!outer) return Iteration::kDescend;
2671 if (!outer->NeedsContext()) {
2672 scope->private_name_lookup_skips_outer_class_ =
2673 outer->private_name_lookup_skips_outer_class();
2674 }
2675 if (!scope->is_function_scope() ||
2676 scope->AsDeclarationScope()->ShouldEagerCompile()) {
2677 return Iteration::kDescend;
2678 }
2679 return Iteration::kContinue;
2680 });
2681}
2682
2683void DeclarationScope::RecordNeedsPrivateNameContextChainRecalc() {
2684 DCHECK_EQ(GetClosureScope(), this)((void) 0);
2685 DeclarationScope* scope;
2686 for (scope = this; scope != nullptr;
2687 scope = scope->outer_scope() != nullptr
2688 ? scope->outer_scope()->GetClosureScope()
2689 : nullptr) {
2690 if (scope->needs_private_name_context_chain_recalc_) return;
2691 scope->needs_private_name_context_chain_recalc_ = true;
2692 }
2693}
2694
2695// static
2696template <typename IsolateT>
2697void DeclarationScope::AllocateScopeInfos(ParseInfo* info, IsolateT* isolate) {
2698 DeclarationScope* scope = info->literal()->scope();
2699
2700 // No one else should have allocated a scope info for this scope yet.
2701 DCHECK(scope->scope_info_.is_null())((void) 0);
2702
2703 MaybeHandle<ScopeInfo> outer_scope;
2704 if (scope->outer_scope_ != nullptr) {
2705 DCHECK((std::is_same<Isolate, v8::internal::Isolate>::value))((void) 0);
2706 outer_scope = scope->outer_scope_->scope_info_;
2707 }
2708
2709 if (scope->needs_private_name_context_chain_recalc()) {
2710 scope->RecalcPrivateNameContextChain();
2711 }
2712 scope->AllocateScopeInfosRecursively(isolate, outer_scope);
2713
2714 // The debugger expects all shared function infos to contain a scope info.
2715 // Since the top-most scope will end up in a shared function info, make sure
2716 // it has one, even if it doesn't need a scope info.
2717 // TODO(yangguo): Remove this requirement.
2718 if (scope->scope_info_.is_null()) {
2719 scope->scope_info_ =
2720 ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope);
2721 }
2722
2723 // Ensuring that the outer script scope has a scope info avoids having
2724 // special case for native contexts vs other contexts.
2725 if (info->script_scope() && info->script_scope()->scope_info_.is_null()) {
2726 info->script_scope()->scope_info_ = isolate->factory()->empty_scope_info();
2727 }
2728}
2729
2730template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
2731 ParseInfo* info, Isolate* isolate);
2732template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos(
2733 ParseInfo* info, LocalIsolate* isolate);
2734
2735int Scope::ContextLocalCount() const {
2736 if (num_heap_slots() == 0) return 0;
2737 Variable* function =
2738 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr;
2739 bool is_function_var_in_context =
2740 function != nullptr && function->IsContextSlot();
2741 return num_heap_slots() - ContextHeaderLength() -
2742 (is_function_var_in_context ? 1 : 0);
2743}
2744
2745VariableProxy* Scope::NewHomeObjectVariableProxy(AstNodeFactory* factory,
2746 const AstRawString* name,
2747 int start_pos) {
2748 // VariableProxies of the home object cannot be resolved like a normal
2749 // variable. Consider the case of a super.property usage in heritage position:
2750 //
2751 // class C extends super.foo { m() { super.bar(); } }
2752 //
2753 // The super.foo property access is logically nested under C's class scope,
2754 // which also has a home object due to its own method m's usage of
2755 // super.bar(). However, super.foo must resolve super in C's outer scope.
2756 //
2757 // Because of the above, home object VariableProxies are always made directly
2758 // on the Scope that needs the home object instead of the innermost scope.
2759 DCHECK(needs_home_object())((void) 0);
2760 if (!scope_info_.is_null()) {
2761 // This is a lazy compile, so the home object's context slot is already
2762 // known.
2763 Variable* home_object = variables_.Lookup(name);
2764 if (home_object == nullptr) {
2765 VariableLookupResult lookup_result;
2766 int index = scope_info_->ContextSlotIndex(name->string(), &lookup_result);
2767 DCHECK_GE(index, 0)((void) 0);
2768 bool was_added;
2769 home_object = variables_.Declare(zone(), this, name, lookup_result.mode,
2770 NORMAL_VARIABLE, lookup_result.init_flag,
2771 lookup_result.maybe_assigned_flag,
2772 IsStaticFlag::kNotStatic, &was_added);
2773 DCHECK(was_added)((void) 0);
2774 home_object->AllocateTo(VariableLocation::CONTEXT, index);
2775 }
2776 return factory->NewVariableProxy(home_object, start_pos);
2777 }
2778 // This is not a lazy compile. Add the unresolved home object VariableProxy to
2779 // the unresolved list of the home object scope, which is not necessarily the
2780 // innermost scope.
2781 VariableProxy* proxy =
2782 factory->NewVariableProxy(name, NORMAL_VARIABLE, start_pos);
2783 AddUnresolved(proxy);
2784 return proxy;
2785}
2786
2787bool IsComplementaryAccessorPair(VariableMode a, VariableMode b) {
2788 switch (a) {
2789 case VariableMode::kPrivateGetterOnly:
2790 return b == VariableMode::kPrivateSetterOnly;
2791 case VariableMode::kPrivateSetterOnly:
2792 return b == VariableMode::kPrivateGetterOnly;
2793 default:
2794 return false;
2795 }
2796}
2797
2798void ClassScope::FinalizeReparsedClassScope(
2799 Isolate* isolate, MaybeHandle<ScopeInfo> maybe_scope_info,
2800 AstValueFactory* ast_value_factory, bool needs_allocation_fixup) {
2801 // Set this bit so that DelcarationScope::Analyze recognizes
2802 // the reparsed instance member initializer scope.
2803#ifdef DEBUG
2804 is_reparsed_class_scope_ = true;
2805#endif
2806
2807 if (!needs_allocation_fixup) {
2808 return;
2809 }
2810
2811 // Restore variable allocation results for context-allocated variables in
2812 // the class scope from ScopeInfo, so that we don't need to run
2813 // resolution and allocation on these variables again when generating
2814 // code for the initializer function.
2815 DCHECK(!maybe_scope_info.is_null())((void) 0);
2816 Handle<ScopeInfo> scope_info = maybe_scope_info.ToHandleChecked();
2817 DCHECK_EQ(scope_info->scope_type(), CLASS_SCOPE)((void) 0);
2818 DCHECK_EQ(scope_info->StartPosition(), start_position_)((void) 0);
2819
2820 int context_header_length = scope_info->ContextHeaderLength();
2821 DisallowGarbageCollection no_gc;
2822 for (auto it : ScopeInfo::IterateLocalNames(scope_info)) {
2823 int slot_index = context_header_length + it->index();
2824 DCHECK_LT(slot_index, scope_info->ContextLength())((void) 0);
2825
2826 const AstRawString* string = ast_value_factory->GetString(
2827 it->name(), SharedStringAccessGuardIfNeeded(isolate));
2828 Variable* var = string->IsPrivateName() ? LookupLocalPrivateName(string)
2829 : LookupLocal(string);
2830 DCHECK_NOT_NULL(var)((void) 0);
2831 var->AllocateTo(VariableLocation::CONTEXT, slot_index);
2832 }
2833 scope_info_ = scope_info;
2834}
2835
2836Variable* ClassScope::DeclarePrivateName(const AstRawString* name,
2837 VariableMode mode,
2838 IsStaticFlag is_static_flag,
2839 bool* was_added) {
2840 Variable* result = EnsureRareData()->private_name_map.Declare(
2841 zone(), this, name, mode, NORMAL_VARIABLE,
2842 InitializationFlag::kNeedsInitialization, MaybeAssignedFlag::kNotAssigned,
2843 is_static_flag, was_added);
2844 if (*was_added) {
2845 locals_.Add(result);
2846 has_static_private_methods_ |=
2847 (result->is_static() &&
2848 IsPrivateMethodOrAccessorVariableMode(result->mode()));
2849 } else if (IsComplementaryAccessorPair(result->mode(), mode) &&
2850 result->is_static_flag() == is_static_flag) {
2851 *was_added = true;
2852 result->set_mode(VariableMode::kPrivateGetterAndSetter);
2853 }
2854 result->ForceContextAllocation();
2855 return result;
2856}
2857
2858Variable* ClassScope::LookupLocalPrivateName(const AstRawString* name) {
2859 RareData* rare_data = GetRareData();
2860 if (rare_data == nullptr) {
2861 return nullptr;
2862 }
2863 return rare_data->private_name_map.Lookup(name);
2864}
2865
2866UnresolvedList::Iterator ClassScope::GetUnresolvedPrivateNameTail() {
2867 RareData* rare_data = GetRareData();
2868 if (rare_data == nullptr) {
2869 return UnresolvedList::Iterator();
2870 }
2871 return rare_data->unresolved_private_names.end();
2872}
2873
2874void ClassScope::ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail) {
2875 RareData* rare_data = GetRareData();
2876 if (rare_data == nullptr ||
2877 rare_data->unresolved_private_names.end() == tail) {
2878 return;
2879 }
2880
2881 bool tail_is_empty = tail == UnresolvedList::Iterator();
2882 if (tail_is_empty) {
2883 // If the saved tail is empty, the list used to be empty, so clear it.
2884 rare_data->unresolved_private_names.Clear();
2885 } else {
2886 rare_data->unresolved_private_names.Rewind(tail);
2887 }
2888}
2889
2890void ClassScope::MigrateUnresolvedPrivateNameTail(
2891 AstNodeFactory* ast_node_factory, UnresolvedList::Iterator tail) {
2892 RareData* rare_data = GetRareData();
2893 if (rare_data == nullptr ||
2894 rare_data->unresolved_private_names.end() == tail) {
2895 return;
2896 }
2897 UnresolvedList migrated_names;
2898
2899 // If the saved tail is empty, the list used to be empty, so we should
2900 // migrate everything after the head.
2901 bool tail_is_empty = tail == UnresolvedList::Iterator();
2902 UnresolvedList::Iterator it =
2903 tail_is_empty ? rare_data->unresolved_private_names.begin() : tail;
2904
2905 for (; it != rare_data->unresolved_private_names.end(); ++it) {
2906 VariableProxy* proxy = *it;
2907 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
2908 migrated_names.Add(copy);
2909 }
2910
2911 // Replace with the migrated copies.
2912 if (tail_is_empty) {
2913 rare_data->unresolved_private_names.Clear();
2914 } else {
2915 rare_data->unresolved_private_names.Rewind(tail);
2916 }
2917 rare_data->unresolved_private_names.Append(std::move(migrated_names));
2918}
2919
2920Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) {
2921 DCHECK(!scope_info_.is_null())((void) 0);
2922 DCHECK_NULL(LookupLocalPrivateName(name))((void) 0);
2923 DisallowGarbageCollection no_gc;
2924
2925 VariableLookupResult lookup_result;
2926 int index = scope_info_->ContextSlotIndex(name->string(), &lookup_result);
2927 if (index < 0) {
2928 return nullptr;
2929 }
2930
2931 DCHECK(IsConstVariableMode(lookup_result.mode))((void) 0);
2932 DCHECK_EQ(lookup_result.init_flag, InitializationFlag::kNeedsInitialization)((void) 0);
2933 DCHECK_EQ(lookup_result.maybe_assigned_flag, MaybeAssignedFlag::kNotAssigned)((void) 0);
2934
2935 // Add the found private name to the map to speed up subsequent
2936 // lookups for the same name.
2937 bool was_added;
2938 Variable* var = DeclarePrivateName(name, lookup_result.mode,
2939 lookup_result.is_static_flag, &was_added);
2940 DCHECK(was_added)((void) 0);
2941 var->AllocateTo(VariableLocation::CONTEXT, index);
2942 return var;
2943}
2944
2945Variable* ClassScope::LookupPrivateName(VariableProxy* proxy) {
2946 DCHECK(!proxy->is_resolved())((void) 0);
2947
2948 for (PrivateNameScopeIterator scope_iter(this); !scope_iter.Done();
2949 scope_iter.Next()) {
2950 ClassScope* scope = scope_iter.GetScope();
2951 // Try finding it in the private name map first, if it can't be found,
2952 // try the deseralized scope info.
2953 Variable* var = scope->LookupLocalPrivateName(proxy->raw_name());
2954 if (var == nullptr && !scope->scope_info_.is_null()) {
2955 var = scope->LookupPrivateNameInScopeInfo(proxy->raw_name());
2956 }
2957 if (var != nullptr) {
2958 return var;
2959 }
2960 }
2961 return nullptr;
2962}
2963
2964bool ClassScope::ResolvePrivateNames(ParseInfo* info) {
2965 RareData* rare_data = GetRareData();
2966 if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) {
2967 return true;
2968 }
2969
2970 UnresolvedList& list = rare_data->unresolved_private_names;
2971 for (VariableProxy* proxy : list) {
2972 Variable* var = LookupPrivateName(proxy);
2973 if (var == nullptr) {
2974 // It's only possible to fail to resolve private names here if
2975 // this is at the top level or the private name is accessed through eval.
2976 DCHECK(info->flags().is_eval() || outer_scope_->is_script_scope())((void) 0);
2977 Scanner::Location loc = proxy->location();
2978 info->pending_error_handler()->ReportMessageAt(
2979 loc.beg_pos, loc.end_pos,
2980 MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name());
2981 return false;
2982 } else {
2983 proxy->BindTo(var);
2984 }
2985 }
2986
2987 // By now all unresolved private names should be resolved so
2988 // clear the list.
2989 list.Clear();
2990 return true;
2991}
2992
2993VariableProxy* ClassScope::ResolvePrivateNamesPartially() {
2994 RareData* rare_data = GetRareData();
2995 if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) {
2996 return nullptr;
2997 }
2998
2999 PrivateNameScopeIterator private_name_scope_iter(this);
3000 private_name_scope_iter.Next();
3001 UnresolvedList& unresolved = rare_data->unresolved_private_names;
3002 bool has_private_names = rare_data->private_name_map.capacity() > 0;
3003
3004 // If the class itself does not have private names, nor does it have
3005 // an outer private name scope, then we are certain any private name access
3006 // inside cannot be resolved.
3007 if (!has_private_names && private_name_scope_iter.Done() &&
3008 !unresolved.is_empty()) {
3009 return unresolved.first();
3010 }
3011
3012 for (VariableProxy* proxy = unresolved.first(); proxy != nullptr;) {
3013 DCHECK(proxy->IsPrivateName())((void) 0);
3014 VariableProxy* next = proxy->next_unresolved();
3015 unresolved.Remove(proxy);
3016 Variable* var = nullptr;
3017
3018 // If we can find private name in the current class scope, we can bind
3019 // them immediately because it's going to shadow any outer private names.
3020 if (has_private_names) {
3021 var = LookupLocalPrivateName(proxy->raw_name());
3022 if (var != nullptr) {
3023 var->set_is_used();
3024 proxy->BindTo(var);
3025 // If the variable being accessed is a static private method, we need to
3026 // save the class variable in the context to check that the receiver is
3027 // the class during runtime.
3028 has_explicit_static_private_methods_access_ |=
3029 (var->is_static() &&
3030 IsPrivateMethodOrAccessorVariableMode(var->mode()));
3031 }
3032 }
3033
3034 // If the current scope does not have declared private names,
3035 // try looking from the outer class scope later.
3036 if (var == nullptr) {
3037 // There's no outer private name scope so we are certain that the variable
3038 // cannot be resolved later.
3039 if (private_name_scope_iter.Done()) {
3040 return proxy;
3041 }
3042
3043 // The private name may be found later in the outer private name scope, so
3044 // push it to the outer sopce.
3045 private_name_scope_iter.AddUnresolvedPrivateName(proxy);
3046 }
3047
3048 proxy = next;
3049 }
3050
3051 DCHECK(unresolved.is_empty())((void) 0);
3052 return nullptr;
3053}
3054
3055Variable* ClassScope::DeclareBrandVariable(AstValueFactory* ast_value_factory,
3056 IsStaticFlag is_static_flag,
3057 int class_token_pos) {
3058 DCHECK_IMPLIES(GetRareData() != nullptr, GetRareData()->brand == nullptr)((void) 0);
3059 bool was_added;
3060 Variable* brand = Declare(zone(), ast_value_factory->dot_brand_string(),
3061 VariableMode::kConst, NORMAL_VARIABLE,
3062 InitializationFlag::kNeedsInitialization,
3063 MaybeAssignedFlag::kNotAssigned, &was_added);
3064 DCHECK(was_added)((void) 0);
3065 brand->set_is_static_flag(is_static_flag);
3066 brand->ForceContextAllocation();
3067 brand->set_is_used();
3068 EnsureRareData()->brand = brand;
3069 brand->set_initializer_position(class_token_pos);
3070 return brand;
3071}
3072
3073Variable* ClassScope::DeclareClassVariable(AstValueFactory* ast_value_factory,
3074 const AstRawString* name,
3075 int class_token_pos) {
3076 DCHECK_NULL(class_variable_)((void) 0);
3077 bool was_added;
3078 class_variable_ =
3079 Declare(zone(), name == nullptr ? ast_value_factory->dot_string() : name,
3080 VariableMode::kConst, NORMAL_VARIABLE,
3081 InitializationFlag::kNeedsInitialization,
3082 MaybeAssignedFlag::kMaybeAssigned, &was_added);
3083 DCHECK(was_added)((void) 0);
3084 class_variable_->set_initializer_position(class_token_pos);
3085 return class_variable_;
3086}
3087
3088PrivateNameScopeIterator::PrivateNameScopeIterator(Scope* start)
3089 : start_scope_(start), current_scope_(start) {
3090 if (!start->is_class_scope() || start->AsClassScope()->IsParsingHeritage()) {
3091 Next();
3092 }
3093}
3094
3095void PrivateNameScopeIterator::Next() {
3096 DCHECK(!Done())((void) 0);
3097 Scope* inner = current_scope_;
3098 Scope* scope = inner->outer_scope();
3099 while (scope != nullptr) {
3100 if (scope->is_class_scope()) {
3101 if (!inner->private_name_lookup_skips_outer_class()) {
3102 current_scope_ = scope;
3103 return;
3104 }
3105 skipped_any_scopes_ = true;
3106 }
3107 inner = scope;
3108 scope = scope->outer_scope();
3109 }
3110 current_scope_ = nullptr;
3111}
3112
3113void PrivateNameScopeIterator::AddUnresolvedPrivateName(VariableProxy* proxy) {
3114 // During a reparse, current_scope_->already_resolved_ may be true here,
3115 // because the class scope is deserialized while the function scope inside may
3116 // be new.
3117 DCHECK(!proxy->is_resolved())((void) 0);
3118 DCHECK(proxy->IsPrivateName())((void) 0);
3119 GetScope()->EnsureRareData()->unresolved_private_names.Add(proxy);
3120 // Any closure scope that contain uses of private names that skips over a
3121 // class scope due to heritage expressions need private name context chain
3122 // recalculation, since not all scopes require a Context or ScopeInfo. See
3123 // comment in DeclarationScope::RecalcPrivateNameContextChain.
3124 if (V8_UNLIKELY(skipped_any_scopes_)(__builtin_expect(!!(skipped_any_scopes_), 0))) {
3125 start_scope_->GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc();
3126 }
3127}
3128
3129} // namespace internal
3130} // namespace v8