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()); 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); 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); 83 DCHECK_EQ(name, p->key); 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); 91 DCHECK_NOT_NULL(p->value); 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); 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); 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); 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); 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); 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); 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); 214 DCHECK_EQ(scope_info->ContextLocalInitFlag(index), 215 InitializationFlag::kNeedsInitialization); 216 DCHECK_EQ(scope_info->ContextLocalMaybeAssignedFlag(index), 217 MaybeAssignedFlag::kMaybeAssigned); 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()); 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()); 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_); 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); 261 int home_object_index = scope_info->ContextSlotIndex( 262 ast_value_factory->dot_home_object_string()->string()); 263 DCHECK_IMPLIES(home_object_index >= 0, 264 scope_type == CLASS_SCOPE || scope_type == BLOCK_SCOPE); 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); 278 SetDefaults(); 279 if (scope_info->SloppyEvalCanExtendVars()) { 280 DCHECK(!is_eval_scope()); 281 sloppy_eval_can_extend_vars_ = true; 282 } 283 if (scope_info->ClassScopeHasPrivateBrand()) { 284 DCHECK(IsClassConstructor(function_kind())); 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); 307 AllocateHeapSlot(variable); 308} 309 310void DeclarationScope::SetDefaults() { 311 is_declaration_scope_ = true; 312 has_simple_parameters_ = true; 313#if V8_ENABLE_WEBASSEMBLY 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_WEBASSEMBLY 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()); 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_WEBASSEMBLY 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); 477 DCHECK_EQ(scope_info.ContextLocalCount(), 1); 478 DCHECK_EQ(scope_info.ContextLocalMode(0), VariableMode::kVar); 479 DCHECK_EQ(scope_info.ContextLocalInitFlag(0), kCreatedInitialized); 480 DCHECK(scope_info.HasInlinedLocalNames()); 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); 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()); 560 return static_cast<DeclarationScope*>(this); 561} 562 563const DeclarationScope* Scope::AsDeclarationScope() const { 564 DCHECK(is_declaration_scope()); 565 return static_cast<const DeclarationScope*>(this); 566} 567 568ModuleScope* Scope::AsModuleScope() { 569 DCHECK(is_module_scope()); 570 return static_cast<ModuleScope*>(this); 571} 572 573const ModuleScope* Scope::AsModuleScope() const { 574 DCHECK(is_module_scope()); 575 return static_cast<const ModuleScope*>(this); 576} 577 578ClassScope* Scope::AsClassScope() { 579 DCHECK(is_class_scope()); 580 return static_cast<ClassScope*>(this); 581} 582 583const ClassScope* Scope::AsClassScope() const { 584 DCHECK(is_class_scope()); 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())); 595 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() || 596 (is_block_scope() && outer_scope()->is_function_scope())); 597 DCHECK(HasSimpleParameters() || is_block_scope() || is_being_lazily_parsed_); 598 DCHECK_EQ(factory == nullptr, is_being_lazily_parsed_); 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() || 606 is_script_scope()); 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_); 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); 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_); 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()); 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() || 704 scope->IsReparsedMemberInitializerScope() || 705 scope->outer_scope()->already_resolved_); 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); 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()); 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()); 748 DCHECK(!is_arrow_scope()); 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()); 781 DCHECK(!is_arrow_scope()); 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); 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); 796 } 797} 798 799Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name, 800 Scope* cache) { 801 DCHECK(is_function_scope()); 802 DCHECK_NULL(function_); 803 if (cache == nullptr) cache = this; 804 DCHECK(this->IsOuterScopeOf(cache)); 805 DCHECK_NULL(cache->variables_.Lookup(name)); 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()); 821 DCHECK_NULL(generator_object_var()); 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()); 831#ifdef DEBUG 832 DCHECK_NE(sibling_, this); 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()); 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() || 870 !AsDeclarationScope()->sloppy_eval_can_extend_vars()); 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_); 885 // Temporaries are only placed in ClosureScopes. 886 DCHECK_EQ(GetClosureScope(), this); 887 locals_.Add(var); 888} 889 890void Scope::Snapshot::Reparent(DeclarationScope* new_parent) { 891 DCHECK_EQ(new_parent, outer_scope_->inner_scope_); 892 DCHECK_EQ(new_parent->outer_scope_, outer_scope_); 893 DCHECK_EQ(new_parent, new_parent->GetClosureScope()); 894 DCHECK_NULL(new_parent->inner_scope_); 895 DCHECK(new_parent->unresolved_list_.is_empty()); 896 Scope* inner_scope = new_parent->sibling_; 897 if (inner_scope != top_inner_scope_) { 898 for (; inner_scope->sibling() != top_inner_scope_; 899 inner_scope = inner_scope->sibling()) { 900 inner_scope->outer_scope_ = new_parent; 901 if (inner_scope->inner_scope_calls_eval_) { 902 new_parent->inner_scope_calls_eval_ = true; 903 } 904 DCHECK_NE(inner_scope, new_parent); 905 } 906 inner_scope->outer_scope_ = new_parent; 907 if (inner_scope->inner_scope_calls_eval_) { 908 new_parent->inner_scope_calls_eval_ = true; 909 } 910 new_parent->inner_scope_ = new_parent->sibling_; 911 inner_scope->sibling_ = nullptr; 912 // Reset the sibling rather than the inner_scope_ since we 913 // want to keep new_parent there. 914 new_parent->sibling_ = top_inner_scope_; 915 } 916 917 new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_, 918 top_unresolved_); 919 920 // Move temporaries allocated for complex parameter initializers. 921 DeclarationScope* outer_closure = outer_scope_->GetClosureScope(); 922 for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) { 923 Variable* local = *it; 924 DCHECK_EQ(VariableMode::kTemporary, local->mode()); 925 DCHECK_EQ(local->scope(), local->scope()->GetClosureScope()); 926 DCHECK_NE(local->scope(), new_parent); 927 local->set_scope(new_parent); 928 } 929 new_parent->locals_.MoveTail(outer_closure->locals(), top_local_); 930 outer_closure->locals_.Rewind(top_local_); 931 932 // Move eval calls since Snapshot's creation into new_parent. 933 if (outer_scope_->calls_eval_) { 934 new_parent->RecordEvalCall(); 935 outer_scope_->calls_eval_ = false; 936 declaration_scope_->sloppy_eval_can_extend_vars_ = false; 937 } 938} 939 940void Scope::ReplaceOuterScope(Scope* outer) { 941 DCHECK_NOT_NULL(outer); 942 DCHECK_NOT_NULL(outer_scope_); 943 DCHECK(!already_resolved_); 944 outer_scope_->RemoveInnerScope(this); 945 outer->AddInnerScope(this); 946 outer_scope_ = outer; 947} 948 949Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) { 950 DCHECK(!scope_info_.is_null()); 951 DCHECK(this->IsOuterScopeOf(cache)); 952 DCHECK(!cache->deserialized_scope_uses_external_cache()); 953 // The case where where the cache can be another scope is when the cache scope 954 // is the last scope that doesn't use an external cache. 955 DCHECK_IMPLIES( 956 cache != this, 957 cache->outer_scope()->deserialized_scope_uses_external_cache()); 958 DCHECK_NULL(cache->variables_.Lookup(name)); 959 DisallowGarbageCollection no_gc; 960 961 String name_handle = *name->string(); 962 ScopeInfo scope_info = *scope_info_; 963 // The Scope is backed up by ScopeInfo. This means it cannot operate in a 964 // heap-independent mode, and all strings must be internalized immediately. So 965 // it's ok to get the Handle<String> here. 966 bool found = false; 967 968 VariableLocation location; 969 int index; 970 VariableLookupResult lookup_result; 971 972 { 973 location = VariableLocation::CONTEXT; 974 index = scope_info.ContextSlotIndex(name->string(), &lookup_result); 975 found = index >= 0; 976 } 977 978 if (!found && is_module_scope()) { 979 location = VariableLocation::MODULE; 980 index = scope_info.ModuleIndex(name_handle, &lookup_result.mode, 981 &lookup_result.init_flag, 982 &lookup_result.maybe_assigned_flag); 983 found = index != 0; 984 } 985 986 if (!found) { 987 index = scope_info.FunctionContextSlotIndex(name_handle); 988 if (index < 0) return nullptr; // Nowhere found. 989 Variable* var = AsDeclarationScope()->DeclareFunctionVar(name, cache); 990 DCHECK_EQ(VariableMode::kConst, var->mode()); 991 var->AllocateTo(VariableLocation::CONTEXT, index); 992 return cache->variables_.Lookup(name); 993 } 994 995 if (!is_module_scope()) { 996 DCHECK_NE(index, scope_info.ReceiverContextSlotIndex()); 997 } 998 999 bool was_added; 1000 Variable* var = cache->variables_.Declare( 1001 zone(), this, name, lookup_result.mode, NORMAL_VARIABLE, 1002 lookup_result.init_flag, lookup_result.maybe_assigned_flag, 1003 IsStaticFlag::kNotStatic, &was_added); 1004 DCHECK(was_added); 1005 var->AllocateTo(location, index); 1006 return var; 1007} 1008 1009Variable* DeclarationScope::DeclareParameter(const AstRawString* name, 1010 VariableMode mode, 1011 bool is_optional, bool is_rest, 1012 AstValueFactory* ast_value_factory, 1013 int position) { 1014 DCHECK(!already_resolved_); 1015 DCHECK(is_function_scope() || is_module_scope()); 1016 DCHECK(!has_rest_); 1017 DCHECK(!is_optional || !is_rest); 1018 DCHECK(!is_being_lazily_parsed_); 1019 DCHECK(!was_lazily_parsed_); 1020 Variable* var; 1021 if (mode == VariableMode::kTemporary) { 1022 var = NewTemporary(name); 1023 } else { 1024 var = LookupLocal(name); 1025 DCHECK_EQ(mode, VariableMode::kVar); 1026 DCHECK(var->is_parameter()); 1027 } 1028 has_rest_ = is_rest; 1029 var->set_initializer_position(position); 1030 params_.Add(var, zone()); 1031 if (!is_rest) ++num_parameters_; 1032 if (name == ast_value_factory->arguments_string()) { 1033 has_arguments_parameter_ = true; 1034 } 1035 // Params are automatically marked as used to make sure that the debugger and 1036 // function.arguments sees them. 1037 // TODO(verwaest): Reevaluate whether we always need to do this, since 1038 // strict-mode function.arguments does not make the arguments available. 1039 var->set_is_used(); 1040 return var; 1041} 1042 1043void DeclarationScope::RecordParameter(bool is_rest) { 1044 DCHECK(!already_resolved_); 1045 DCHECK(is_function_scope() || is_module_scope()); 1046 DCHECK(is_being_lazily_parsed_); 1047 DCHECK(!has_rest_); 1048 has_rest_ = is_rest; 1049 if (!is_rest) ++num_parameters_; 1050} 1051 1052Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, 1053 VariableKind kind, bool* was_added, 1054 InitializationFlag init_flag) { 1055 DCHECK(!already_resolved_); 1056 // Private methods should be declared with ClassScope::DeclarePrivateName() 1057 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode)); 1058 // This function handles VariableMode::kVar, VariableMode::kLet, and 1059 // VariableMode::kConst modes. VariableMode::kDynamic variables are 1060 // introduced during variable allocation, and VariableMode::kTemporary 1061 // variables are allocated via NewTemporary(). 1062 DCHECK(IsDeclaredVariableMode(mode)); 1063 DCHECK_IMPLIES(GetDeclarationScope()->is_being_lazily_parsed(), 1064 mode == VariableMode::kVar || mode == VariableMode::kLet || 1065 mode == VariableMode::kConst); 1066 DCHECK(!GetDeclarationScope()->was_lazily_parsed()); 1067 Variable* var = 1068 Declare(zone(), name, mode, kind, init_flag, kNotAssigned, was_added); 1069 1070 // Pessimistically assume that top-level variables will be assigned and used. 1071 // 1072 // Top-level variables in a script can be accessed by other scripts or even 1073 // become global properties. While this does not apply to top-level variables 1074 // in a module (assuming they are not exported), we must still mark these as 1075 // assigned because they might be accessed by a lazily parsed top-level 1076 // function, which, for efficiency, we preparse without variable tracking. 1077 if (is_script_scope() || is_module_scope()) { 1078 if (mode != VariableMode::kConst) var->SetMaybeAssigned(); 1079 var->set_is_used(); 1080 } 1081 1082 return var; 1083} 1084 1085Variable* Scope::DeclareVariable( 1086 Declaration* declaration, const AstRawString* name, int pos, 1087 VariableMode mode, VariableKind kind, InitializationFlag init, 1088 bool* was_added, bool* sloppy_mode_block_scope_function_redefinition, 1089 bool* ok) { 1090 // Private methods should be declared with ClassScope::DeclarePrivateName() 1091 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode)); 1092 DCHECK(IsDeclaredVariableMode(mode)); 1093 DCHECK(!already_resolved_); 1094 DCHECK(!GetDeclarationScope()->is_being_lazily_parsed()); 1095 DCHECK(!GetDeclarationScope()->was_lazily_parsed()); 1096 1097 if (mode == VariableMode::kVar && !is_declaration_scope()) { 1098 return GetDeclarationScope()->DeclareVariable( 1099 declaration, name, pos, mode, kind, init, was_added, 1100 sloppy_mode_block_scope_function_redefinition, ok); 1101 } 1102 DCHECK(!is_catch_scope()); 1103 DCHECK(!is_with_scope()); 1104 DCHECK(is_declaration_scope() || 1105 (IsLexicalVariableMode(mode) && is_block_scope())); 1106 1107 DCHECK_NOT_NULL(name); 1108 1109 Variable* var = LookupLocal(name); 1110 // Declare the variable in the declaration scope. 1111 *was_added = var == nullptr; 1112 if (V8_LIKELY(*was_added)) { 1113 if (V8_UNLIKELY(is_eval_scope() && is_sloppy(language_mode()) && 1114 mode == VariableMode::kVar)) { 1115 // In a var binding in a sloppy direct eval, pollute the enclosing scope 1116 // with this new binding by doing the following: 1117 // The proxy is bound to a lookup variable to force a dynamic declaration 1118 // using the DeclareEvalVar or DeclareEvalFunction runtime functions. 1119 DCHECK_EQ(NORMAL_VARIABLE, kind); 1120 var = NonLocal(name, VariableMode::kDynamic); 1121 // Mark the var as used in case anyone outside the eval wants to use it. 1122 var->set_is_used(); 1123 } else { 1124 // Declare the name. 1125 var = DeclareLocal(name, mode, kind, was_added, init); 1126 DCHECK(*was_added); 1127 } 1128 } else { 1129 var->SetMaybeAssigned(); 1130 if (V8_UNLIKELY(IsLexicalVariableMode(mode) || 1131 IsLexicalVariableMode(var->mode()))) { 1132 // The name was declared in this scope before; check for conflicting 1133 // re-declarations. We have a conflict if either of the declarations is 1134 // not a var (in script scope, we also have to ignore legacy const for 1135 // compatibility). There is similar code in runtime.cc in the Declare 1136 // functions. The function CheckConflictingVarDeclarations checks for 1137 // var and let bindings from different scopes whereas this is a check 1138 // for conflicting declarations within the same scope. This check also 1139 // covers the special case 1140 // 1141 // function () { let x; { var x; } } 1142 // 1143 // because the var declaration is hoisted to the function scope where 1144 // 'x' is already bound. 1145 // 1146 // In harmony we treat re-declarations as early errors. See ES5 16 for a 1147 // definition of early errors. 1148 // 1149 // Allow duplicate function decls for web compat, see bug 4693. 1150 *ok = var->is_sloppy_block_function() && 1151 kind == SLOPPY_BLOCK_FUNCTION_VARIABLE; 1152 *sloppy_mode_block_scope_function_redefinition = *ok; 1153 } 1154 } 1155 DCHECK_NOT_NULL(var); 1156 1157 // We add a declaration node for every declaration. The compiler 1158 // will only generate code if necessary. In particular, declarations 1159 // for inner local variables that do not represent functions won't 1160 // result in any generated code. 1161 // 1162 // This will lead to multiple declaration nodes for the 1163 // same variable if it is declared several times. This is not a 1164 // semantic issue, but it may be a performance issue since it may 1165 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls. 1166 decls_.Add(declaration); 1167 declaration->set_var(var); 1168 return var; 1169} 1170 1171Variable* Scope::DeclareVariableName(const AstRawString* name, 1172 VariableMode mode, bool* was_added, 1173 VariableKind kind) { 1174 DCHECK(IsDeclaredVariableMode(mode)); 1175 DCHECK(!already_resolved_); 1176 DCHECK(GetDeclarationScope()->is_being_lazily_parsed()); 1177 // Private methods should be declared with ClassScope::DeclarePrivateName() 1178 DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode)); 1179 if (mode == VariableMode::kVar && !is_declaration_scope()) { 1180 return GetDeclarationScope()->DeclareVariableName(name, mode, was_added, 1181 kind); 1182 } 1183 DCHECK(!is_with_scope()); 1184 DCHECK(!is_eval_scope()); 1185 DCHECK(is_declaration_scope() || IsLexicalVariableMode(mode)); 1186 DCHECK(scope_info_.is_null()); 1187 1188 // Declare the variable in the declaration scope. 1189 Variable* var = DeclareLocal(name, mode, kind, was_added); 1190 if (!*was_added) { 1191 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())) { 1192 if (!var->is_sloppy_block_function() || 1193 kind != SLOPPY_BLOCK_FUNCTION_VARIABLE) { 1194 // Duplicate functions are allowed in the sloppy mode, but if this is 1195 // not a function declaration, it's an error. This is an error PreParser 1196 // hasn't previously detected. 1197 return nullptr; 1198 } 1199 // Sloppy block function redefinition. 1200 } 1201 var->SetMaybeAssigned(); 1202 } 1203 var->set_is_used(); 1204 return var; 1205} 1206 1207Variable* Scope::DeclareCatchVariableName(const AstRawString* name) { 1208 DCHECK(!already_resolved_); 1209 DCHECK(is_catch_scope()); 1210 DCHECK(scope_info_.is_null()); 1211 1212 bool was_added; 1213 Variable* result = Declare(zone(), name, VariableMode::kVar, NORMAL_VARIABLE, 1214 kCreatedInitialized, kNotAssigned, &was_added); 1215 DCHECK(was_added); 1216 return result; 1217} 1218 1219void Scope::AddUnresolved(VariableProxy* proxy) { 1220 DCHECK(!already_resolved_); 1221 DCHECK(!proxy->is_resolved()); 1222 unresolved_list_.Add(proxy); 1223} 1224 1225Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, 1226 VariableKind kind, 1227 Scope* cache) { 1228 DCHECK(is_script_scope()); 1229 bool was_added; 1230 return cache->variables_.Declare( 1231 zone(), this, name, VariableMode::kDynamicGlobal, kind, 1232 kCreatedInitialized, kNotAssigned, IsStaticFlag::kNotStatic, &was_added); 1233 // TODO(neis): Mark variable as maybe-assigned? 1234} 1235 1236bool Scope::RemoveUnresolved(VariableProxy* var) { 1237 return unresolved_list_.Remove(var); 1238} 1239 1240void Scope::DeleteUnresolved(VariableProxy* var) { 1241 DCHECK(unresolved_list_.Contains(var)); 1242 var->mark_removed_from_unresolved(); 1243} 1244 1245Variable* Scope::NewTemporary(const AstRawString* name) { 1246 return NewTemporary(name, kMaybeAssigned); 1247} 1248 1249Variable* Scope::NewTemporary(const AstRawString* name, 1250 MaybeAssignedFlag maybe_assigned) { 1251 DeclarationScope* scope = GetClosureScope(); 1252 Variable* var = zone()->New<Variable>(scope, name, VariableMode::kTemporary, 1253 NORMAL_VARIABLE, kCreatedInitialized); 1254 scope->AddLocal(var); 1255 if (maybe_assigned == kMaybeAssigned) var->SetMaybeAssigned(); 1256 return var; 1257} 1258 1259Declaration* DeclarationScope::CheckConflictingVarDeclarations( 1260 bool* allowed_catch_binding_var_redeclaration) { 1261 if (has_checked_syntax_) return nullptr; 1262 for (Declaration* decl : decls_) { 1263 // Lexical vs lexical conflicts within the same scope have already been 1264 // captured in Parser::Declare. The only conflicts we still need to check 1265 // are lexical vs nested var. 1266 if (decl->IsVariableDeclaration() && 1267 decl->AsVariableDeclaration()->AsNested() != nullptr) { 1268 Scope* current = decl->AsVariableDeclaration()->AsNested()->scope(); 1269 DCHECK(decl->var()->mode() == VariableMode::kVar || 1270 decl->var()->mode() == VariableMode::kDynamic); 1271 // Iterate through all scopes until the declaration scope. 1272 do { 1273 // There is a conflict if there exists a non-VAR binding. 1274 Variable* other_var = current->LookupLocal(decl->var()->raw_name()); 1275 if (current->is_catch_scope()) { 1276 *allowed_catch_binding_var_redeclaration |= other_var != nullptr; 1277 current = current->outer_scope(); 1278 continue; 1279 } 1280 if (other_var != nullptr) { 1281 DCHECK(IsLexicalVariableMode(other_var->mode())); 1282 return decl; 1283 } 1284 current = current->outer_scope(); 1285 } while (current != this); 1286 } 1287 } 1288 1289 if (V8_LIKELY(!is_eval_scope())) return nullptr; 1290 if (!is_sloppy(language_mode())) return nullptr; 1291 1292 // Var declarations in sloppy eval are hoisted to the first non-eval 1293 // declaration scope. Check for conflicts between the eval scope that 1294 // declaration scope. 1295 Scope* end = outer_scope()->GetNonEvalDeclarationScope()->outer_scope(); 1296 1297 for (Declaration* decl : decls_) { 1298 if (IsLexicalVariableMode(decl->var()->mode())) continue; 1299 Scope* current = outer_scope_; 1300 // Iterate through all scopes until and including the declaration scope. 1301 do { 1302 // There is a conflict if there exists a non-VAR binding up to the 1303 // declaration scope in which this sloppy-eval runs. 1304 // 1305 // Use the current scope as the cache, since the general cache would be 1306 // the end scope. 1307 Variable* other_var = 1308 current->LookupInScopeOrScopeInfo(decl->var()->raw_name(), current); 1309 if (other_var != nullptr && !current->is_catch_scope()) { 1310 // If this is a VAR, then we know that it doesn't conflict with 1311 // anything, so we can't conflict with anything either. The one 1312 // exception is the binding variable in catch scopes, which is handled 1313 // by the if above. 1314 if (!IsLexicalVariableMode(other_var->mode())) break; 1315 return decl; 1316 } 1317 current = current->outer_scope(); 1318 } while (current != end); 1319 } 1320 return nullptr; 1321} 1322 1323const AstRawString* Scope::FindVariableDeclaredIn(Scope* scope, 1324 VariableMode mode_limit) { 1325 const VariableMap& variables = scope->variables_; 1326 for (ZoneHashMap::Entry* p = variables.Start(); p != nullptr; 1327 p = variables.Next(p)) { 1328 const AstRawString* name = static_cast<const AstRawString*>(p->key); 1329 Variable* var = LookupLocal(name); 1330 if (var != nullptr && var->mode() <= mode_limit) return name; 1331 } 1332 return nullptr; 1333} 1334 1335void DeclarationScope::DeserializeReceiver(AstValueFactory* ast_value_factory) { 1336 if (is_script_scope()) { 1337 DCHECK_NOT_NULL(receiver_); 1338 return; 1339 } 1340 DCHECK(has_this_declaration()); 1341 DeclareThis(ast_value_factory); 1342 if (is_debug_evaluate_scope()) { 1343 receiver_->AllocateTo(VariableLocation::LOOKUP, -1); 1344 } else { 1345 receiver_->AllocateTo(VariableLocation::CONTEXT, 1346 scope_info_->ReceiverContextSlotIndex()); 1347 } 1348} 1349 1350bool DeclarationScope::AllocateVariables(ParseInfo* info) { 1351 // Module variables must be allocated before variable resolution 1352 // to ensure that UpdateNeedsHoleCheck() can detect import variables. 1353 if (is_module_scope()) AsModuleScope()->AllocateModuleVariables(); 1354 1355 PrivateNameScopeIterator private_name_scope_iter(this); 1356 if (!private_name_scope_iter.Done() && 1357 !private_name_scope_iter.GetScope()->ResolvePrivateNames(info)) { 1358 DCHECK(info->pending_error_handler()->has_pending_error()); 1359 return false; 1360 } 1361 1362 if (!ResolveVariablesRecursively(info->scope())) { 1363 DCHECK(info->pending_error_handler()->has_pending_error()); 1364 return false; 1365 } 1366 1367 // Don't allocate variables of preparsed scopes. 1368 if (!was_lazily_parsed()) AllocateVariablesRecursively(); 1369 1370 return true; 1371} 1372 1373bool Scope::HasThisReference() const { 1374 if (is_declaration_scope() && AsDeclarationScope()->has_this_reference()) { 1375 return true; 1376 } 1377 1378 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1379 if (!scope->is_declaration_scope() || 1380 !scope->AsDeclarationScope()->has_this_declaration()) { 1381 if (scope->HasThisReference()) return true; 1382 } 1383 } 1384 1385 return false; 1386} 1387 1388bool Scope::AllowsLazyParsingWithoutUnresolvedVariables( 1389 const Scope* outer) const { 1390 // If none of the outer scopes need to decide whether to context allocate 1391 // specific variables, we can preparse inner functions without unresolved 1392 // variables. Otherwise we need to find unresolved variables to force context 1393 // allocation of the matching declarations. We can stop at the outer scope for 1394 // the parse, since context allocation of those variables is already 1395 // guaranteed to be correct. 1396 for (const Scope* s = this; s != outer; s = s->outer_scope_) { 1397 // Eval forces context allocation on all outer scopes, so we don't need to 1398 // look at those scopes. Sloppy eval makes top-level non-lexical variables 1399 // dynamic, whereas strict-mode requires context allocation. 1400 if (s->is_eval_scope()) return is_sloppy(s->language_mode()); 1401 // Catch scopes force context allocation of all variables. 1402 if (s->is_catch_scope()) continue; 1403 // With scopes do not introduce variables that need allocation. 1404 if (s->is_with_scope()) continue; 1405 DCHECK(s->is_module_scope() || s->is_block_scope() || 1406 s->is_function_scope()); 1407 return false; 1408 } 1409 return true; 1410} 1411 1412bool DeclarationScope::AllowsLazyCompilation() const { 1413 // Functions which force eager compilation and class member initializer 1414 // functions are not lazily compilable. 1415 return !force_eager_compilation_ && 1416 !IsClassMembersInitializerFunction(function_kind()); 1417} 1418 1419int Scope::ContextChainLength(Scope* scope) const { 1420 int n = 0; 1421 for (const Scope* s = this; s != scope; s = s->outer_scope_) { 1422 DCHECK_NOT_NULL(s); // scope must be in the scope chain 1423 if (s->NeedsContext()) n++; 1424 } 1425 return n; 1426} 1427 1428int Scope::ContextChainLengthUntilOutermostSloppyEval() const { 1429 int result = 0; 1430 int length = 0; 1431 1432 for (const Scope* s = this; s != nullptr; s = s->outer_scope()) { 1433 if (!s->NeedsContext()) continue; 1434 length++; 1435 if (s->is_declaration_scope() && 1436 s->AsDeclarationScope()->sloppy_eval_can_extend_vars()) { 1437 result = length; 1438 } 1439 } 1440 1441 return result; 1442} 1443 1444DeclarationScope* Scope::GetDeclarationScope() { 1445 Scope* scope = this; 1446 while (!scope->is_declaration_scope()) { 1447 scope = scope->outer_scope(); 1448 } 1449 return scope->AsDeclarationScope(); 1450} 1451 1452DeclarationScope* Scope::GetNonEvalDeclarationScope() { 1453 Scope* scope = this; 1454 while (!scope->is_declaration_scope() || scope->is_eval_scope()) { 1455 scope = scope->outer_scope(); 1456 } 1457 return scope->AsDeclarationScope(); 1458} 1459 1460const DeclarationScope* Scope::GetClosureScope() const { 1461 const Scope* scope = this; 1462 while (!scope->is_declaration_scope() || scope->is_block_scope()) { 1463 scope = scope->outer_scope(); 1464 } 1465 return scope->AsDeclarationScope(); 1466} 1467 1468DeclarationScope* Scope::GetClosureScope() { 1469 Scope* scope = this; 1470 while (!scope->is_declaration_scope() || scope->is_block_scope()) { 1471 scope = scope->outer_scope(); 1472 } 1473 return scope->AsDeclarationScope(); 1474} 1475 1476bool Scope::NeedsScopeInfo() const { 1477 DCHECK(!already_resolved_); 1478 DCHECK(GetClosureScope()->ShouldEagerCompile()); 1479 // The debugger expects all functions to have scope infos. 1480 // TODO(yangguo): Remove this requirement. 1481 if (is_function_scope()) return true; 1482 return NeedsContext(); 1483} 1484 1485bool Scope::ShouldBanArguments() { 1486 return GetReceiverScope()->should_ban_arguments(); 1487} 1488 1489DeclarationScope* Scope::GetReceiverScope() { 1490 Scope* scope = this; 1491 while (!scope->is_declaration_scope() || 1492 (!scope->is_script_scope() && 1493 !scope->AsDeclarationScope()->has_this_declaration())) { 1494 scope = scope->outer_scope(); 1495 } 1496 return scope->AsDeclarationScope(); 1497} 1498 1499DeclarationScope* Scope::GetConstructorScope() { 1500 Scope* scope = this; 1501 while (scope != nullptr && !scope->IsConstructorScope()) { 1502 scope = scope->outer_scope(); 1503 } 1504 if (scope == nullptr) { 1505 return nullptr; 1506 } 1507 DCHECK(scope->IsConstructorScope()); 1508 return scope->AsDeclarationScope(); 1509} 1510 1511Scope* Scope::GetHomeObjectScope() { 1512 Scope* scope = this; 1513 while (scope != nullptr && !scope->is_home_object_scope()) { 1514 if (scope->is_function_scope()) { 1515 FunctionKind function_kind = scope->AsDeclarationScope()->function_kind(); 1516 // "super" in arrow functions binds outside the arrow function. But if we 1517 // find a function which doesn't bind "super" (is not a method etc.) and 1518 // not an arrow function, we know "super" here doesn't bind anywhere and 1519 // we can return nullptr. 1520 if (!IsArrowFunction(function_kind) && !BindsSuper(function_kind)) { 1521 return nullptr; 1522 } 1523 } 1524 if (scope->private_name_lookup_skips_outer_class()) { 1525 DCHECK(scope->outer_scope()->is_class_scope()); 1526 scope = scope->outer_scope()->outer_scope(); 1527 } else { 1528 scope = scope->outer_scope(); 1529 } 1530 } 1531 return scope; 1532} 1533 1534DeclarationScope* Scope::GetScriptScope() { 1535 Scope* scope = this; 1536 while (!scope->is_script_scope()) { 1537 scope = scope->outer_scope(); 1538 } 1539 return scope->AsDeclarationScope(); 1540} 1541 1542Scope* Scope::GetOuterScopeWithContext() { 1543 Scope* scope = outer_scope_; 1544 while (scope && !scope->NeedsContext()) { 1545 scope = scope->outer_scope(); 1546 } 1547 return scope; 1548} 1549 1550namespace { 1551bool WasLazilyParsed(Scope* scope) { 1552 return scope->is_declaration_scope() && 1553 scope->AsDeclarationScope()->was_lazily_parsed(); 1554} 1555 1556} // namespace 1557 1558template <typename FunctionType> 1559void Scope::ForEach(FunctionType callback) { 1560 Scope* scope = this; 1561 while (true) { 1562 Iteration iteration = callback(scope); 1563 // Try to descend into inner scopes first. 1564 if ((iteration == Iteration::kDescend) && scope->inner_scope_ != nullptr) { 1565 scope = scope->inner_scope_; 1566 } else { 1567 // Find the next outer scope with a sibling. 1568 while (scope->sibling_ == nullptr) { 1569 if (scope == this) return; 1570 scope = scope->outer_scope_; 1571 } 1572 if (scope == this) return; 1573 scope = scope->sibling_; 1574 } 1575 } 1576} 1577 1578bool Scope::IsConstructorScope() const { 1579 return is_declaration_scope() && 1580 IsClassConstructor(AsDeclarationScope()->function_kind()); 1581} 1582 1583bool Scope::IsOuterScopeOf(Scope* other) const { 1584 Scope* scope = other; 1585 while (scope) { 1586 if (scope == this) return true; 1587 scope = scope->outer_scope(); 1588 } 1589 return false; 1590} 1591 1592void Scope::CollectNonLocals(DeclarationScope* max_outer_scope, 1593 Isolate* isolate, Handle<StringSet>* non_locals) { 1594 this->ForEach([max_outer_scope, isolate, non_locals](Scope* scope) { 1595 // Module variables must be allocated before variable resolution 1596 // to ensure that UpdateNeedsHoleCheck() can detect import variables. 1597 if (scope->is_module_scope()) { 1598 scope->AsModuleScope()->AllocateModuleVariables(); 1599 } 1600 1601 // Lazy parsed declaration scopes are already partially analyzed. If there 1602 // are unresolved references remaining, they just need to be resolved in 1603 // outer scopes. 1604 Scope* lookup = WasLazilyParsed(scope) ? scope->outer_scope() : scope; 1605 1606 for (VariableProxy* proxy : scope->unresolved_list_) { 1607 DCHECK(!proxy->is_resolved()); 1608 Variable* var = 1609 Lookup<kParsedScope>(proxy, lookup, max_outer_scope->outer_scope()); 1610 if (var == nullptr) { 1611 *non_locals = StringSet::Add(isolate, *non_locals, proxy->name()); 1612 } else { 1613 // In this case we need to leave scopes in a way that they can be 1614 // allocated. If we resolved variables from lazy parsed scopes, we need 1615 // to context allocate the var. 1616 scope->ResolveTo(proxy, var); 1617 if (!var->is_dynamic() && lookup != scope) 1618 var->ForceContextAllocation(); 1619 } 1620 } 1621 1622 // Clear unresolved_list_ as it's in an inconsistent state. 1623 scope->unresolved_list_.Clear(); 1624 return Iteration::kDescend; 1625 }); 1626} 1627 1628void Scope::AnalyzePartially(DeclarationScope* max_outer_scope, 1629 AstNodeFactory* ast_node_factory, 1630 UnresolvedList* new_unresolved_list, 1631 bool maybe_in_arrowhead) { 1632 this->ForEach([max_outer_scope, ast_node_factory, new_unresolved_list, 1633 maybe_in_arrowhead](Scope* scope) { 1634 DCHECK_IMPLIES(scope->is_declaration_scope(), 1635 !scope->AsDeclarationScope()->was_lazily_parsed()); 1636 1637 for (VariableProxy* proxy = scope->unresolved_list_.first(); 1638 proxy != nullptr; proxy = proxy->next_unresolved()) { 1639 if (proxy->is_removed_from_unresolved()) continue; 1640 DCHECK(!proxy->is_resolved()); 1641 Variable* var = 1642 Lookup<kParsedScope>(proxy, scope, max_outer_scope->outer_scope()); 1643 if (var == nullptr) { 1644 // Don't copy unresolved references to the script scope, unless it's a 1645 // reference to a private name or method. In that case keep it so we 1646 // can fail later. 1647 if (!max_outer_scope->outer_scope()->is_script_scope() || 1648 maybe_in_arrowhead) { 1649 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); 1650 new_unresolved_list->Add(copy); 1651 } 1652 } else { 1653 var->set_is_used(); 1654 if (proxy->is_assigned()) var->SetMaybeAssigned(); 1655 } 1656 } 1657 1658 // Clear unresolved_list_ as it's in an inconsistent state. 1659 scope->unresolved_list_.Clear(); 1660 return Iteration::kDescend; 1661 }); 1662} 1663 1664Handle<StringSet> DeclarationScope::CollectNonLocals( 1665 Isolate* isolate, Handle<StringSet> non_locals) { 1666 Scope::CollectNonLocals(this, isolate, &non_locals); 1667 return non_locals; 1668} 1669 1670void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, 1671 bool aborted) { 1672 DCHECK(is_function_scope()); 1673 1674 // Reset all non-trivial members. 1675 params_.DropAndClear(); 1676 decls_.Clear(); 1677 locals_.Clear(); 1678 inner_scope_ = nullptr; 1679 unresolved_list_.Clear(); 1680 sloppy_block_functions_.Clear(); 1681 rare_data_ = nullptr; 1682 has_rest_ = false; 1683 function_ = nullptr; 1684 1685 DCHECK_NE(zone(), ast_value_factory->single_parse_zone()); 1686 // Make sure this scope and zone aren't used for allocation anymore. 1687 { 1688 // Get the zone, while variables_ is still valid 1689 Zone* zone = this->zone(); 1690 variables_.Invalidate(); 1691 zone->Reset(); 1692 } 1693 1694 if (aborted) { 1695 // Prepare scope for use in the outer zone. 1696 variables_ = VariableMap(ast_value_factory->single_parse_zone()); 1697 if (!IsArrowFunction(function_kind_)) { 1698 has_simple_parameters_ = true; 1699 DeclareDefaultFunctionVariables(ast_value_factory); 1700 } 1701 } 1702 1703#ifdef DEBUG 1704 needs_migration_ = false; 1705 is_being_lazily_parsed_ = false; 1706#endif 1707 1708 was_lazily_parsed_ = !aborted; 1709} 1710 1711bool Scope::IsSkippableFunctionScope() { 1712 // Lazy non-arrow function scopes are skippable. Lazy functions are exactly 1713 // those Scopes which have their own PreparseDataBuilder object. This 1714 // logic ensures that the scope allocation data is consistent with the 1715 // skippable function data (both agree on where the lazy function boundaries 1716 // are). 1717 if (!is_function_scope()) return false; 1718 DeclarationScope* declaration_scope = AsDeclarationScope(); 1719 return !declaration_scope->is_arrow_scope() && 1720 declaration_scope->preparse_data_builder() != nullptr; 1721} 1722 1723void Scope::SavePreparseData(Parser* parser) { 1724 this->ForEach([parser](Scope* scope) { 1725 if (scope->IsSkippableFunctionScope()) { 1726 scope->AsDeclarationScope()->SavePreparseDataForDeclarationScope(parser); 1727 } 1728 return Iteration::kDescend; 1729 }); 1730} 1731 1732void DeclarationScope::SavePreparseDataForDeclarationScope(Parser* parser) { 1733 if (preparse_data_builder_ == nullptr) return; 1734 preparse_data_builder_->SaveScopeAllocationData(this, parser); 1735} 1736 1737void DeclarationScope::AnalyzePartially(Parser* parser, 1738 AstNodeFactory* ast_node_factory, 1739 bool maybe_in_arrowhead) { 1740 DCHECK(!force_eager_compilation_); 1741 UnresolvedList new_unresolved_list; 1742 if (!IsArrowFunction(function_kind_) && 1743 (!outer_scope_->is_script_scope() || maybe_in_arrowhead || 1744 (preparse_data_builder_ != nullptr && 1745 preparse_data_builder_->HasInnerFunctions()))) { 1746 // Try to resolve unresolved variables for this Scope and migrate those 1747 // which cannot be resolved inside. It doesn't make sense to try to resolve 1748 // them in the outer Scopes here, because they are incomplete. 1749 Scope::AnalyzePartially(this, ast_node_factory, &new_unresolved_list, 1750 maybe_in_arrowhead); 1751 1752 // Migrate function_ to the right Zone. 1753 if (function_ != nullptr) { 1754 function_ = ast_node_factory->CopyVariable(function_); 1755 } 1756 1757 SavePreparseData(parser); 1758 } 1759 1760#ifdef DEBUG 1761 if (FLAG_print_scopes) { 1762 PrintF("Inner function scope:\n"); 1763 Print(); 1764 } 1765#endif 1766 1767 ResetAfterPreparsing(ast_node_factory->ast_value_factory(), false); 1768 1769 unresolved_list_ = std::move(new_unresolved_list); 1770} 1771 1772void DeclarationScope::RewriteReplGlobalVariables() { 1773 DCHECK(is_script_scope()); 1774 if (!is_repl_mode_scope()) return; 1775 1776 for (VariableMap::Entry* p = variables_.Start(); p != nullptr; 1777 p = variables_.Next(p)) { 1778 Variable* var = reinterpret_cast<Variable*>(p->value); 1779 var->RewriteLocationForRepl(); 1780 } 1781} 1782 1783#ifdef DEBUG 1784namespace { 1785 1786const char* Header(ScopeType scope_type, FunctionKind function_kind, 1787 bool is_declaration_scope) { 1788 switch (scope_type) { 1789 case EVAL_SCOPE: return "eval"; 1790 case FUNCTION_SCOPE: 1791 if (IsGeneratorFunction(function_kind)) return "function*"; 1792 if (IsAsyncFunction(function_kind)) return "async function"; 1793 if (IsArrowFunction(function_kind)) return "arrow"; 1794 return "function"; 1795 case MODULE_SCOPE: return "module"; 1796 case SCRIPT_SCOPE: return "global"; 1797 case CATCH_SCOPE: return "catch"; 1798 case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block"; 1799 case CLASS_SCOPE: 1800 return "class"; 1801 case WITH_SCOPE: return "with"; 1802 } 1803 UNREACHABLE(); 1804} 1805 1806void Indent(int n, const char* str) { PrintF("%*s%s", n, "", str); } 1807 1808void PrintName(const AstRawString* name) { 1809 PrintF("%.*s", name->length(), name->raw_data()); 1810} 1811 1812void PrintLocation(Variable* var) { 1813 switch (var->location()) { 1814 case VariableLocation::UNALLOCATED: 1815 break; 1816 case VariableLocation::PARAMETER: 1817 PrintF("parameter[%d]", var->index()); 1818 break; 1819 case VariableLocation::LOCAL: 1820 PrintF("local[%d]", var->index()); 1821 break; 1822 case VariableLocation::CONTEXT: 1823 PrintF("context[%d]", var->index()); 1824 break; 1825 case VariableLocation::LOOKUP: 1826 PrintF("lookup"); 1827 break; 1828 case VariableLocation::MODULE: 1829 PrintF("module"); 1830 break; 1831 case VariableLocation::REPL_GLOBAL: 1832 PrintF("repl global[%d]", var->index()); 1833 break; 1834 } 1835} 1836 1837void PrintVar(int indent, Variable* var) { 1838 Indent(indent, VariableMode2String(var->mode())); 1839 PrintF(" "); 1840 if (var->raw_name()->IsEmpty()) 1841 PrintF(".%p", reinterpret_cast<void*>(var)); 1842 else 1843 PrintName(var->raw_name()); 1844 PrintF("; // (%p) ", reinterpret_cast<void*>(var)); 1845 PrintLocation(var); 1846 bool comma = !var->IsUnallocated(); 1847 if (var->has_forced_context_allocation()) { 1848 if (comma) PrintF(", "); 1849 PrintF("forced context allocation"); 1850 comma = true; 1851 } 1852 if (var->maybe_assigned() == kNotAssigned) { 1853 if (comma) PrintF(", "); 1854 PrintF("never assigned"); 1855 comma = true; 1856 } 1857 if (var->initialization_flag() == kNeedsInitialization && 1858 !var->binding_needs_init()) { 1859 if (comma) PrintF(", "); 1860 PrintF("hole initialization elided"); 1861 } 1862 PrintF("\n"); 1863} 1864 1865void PrintMap(int indent, const char* label, VariableMap* map, bool locals, 1866 Variable* function_var) { 1867 bool printed_label = false; 1868 for (VariableMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { 1869 Variable* var = reinterpret_cast<Variable*>(p->value); 1870 if (var == function_var) continue; 1871 bool local = !IsDynamicVariableMode(var->mode()); 1872 if ((locals ? local : !local) && 1873 (var->is_used() || !var->IsUnallocated())) { 1874 if (!printed_label) { 1875 Indent(indent, label); 1876 printed_label = true; 1877 } 1878 PrintVar(indent, var); 1879 } 1880 } 1881} 1882 1883} // anonymous namespace 1884 1885void DeclarationScope::PrintParameters() { 1886 PrintF(" ("); 1887 for (int i = 0; i < params_.length(); i++) { 1888 if (i > 0) PrintF(", "); 1889 const AstRawString* name = params_[i]->raw_name(); 1890 if (name->IsEmpty()) { 1891 PrintF(".%p", reinterpret_cast<void*>(params_[i])); 1892 } else { 1893 PrintName(name); 1894 } 1895 } 1896 PrintF(")"); 1897} 1898 1899void Scope::Print(int n) { 1900 int n0 = (n > 0 ? n : 0); 1901 int n1 = n0 + 2; // indentation 1902 1903 // Print header. 1904 FunctionKind function_kind = is_function_scope() 1905 ? AsDeclarationScope()->function_kind() 1906 : FunctionKind::kNormalFunction; 1907 Indent(n0, Header(scope_type_, function_kind, is_declaration_scope())); 1908 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) { 1909 PrintF(" "); 1910 PrintName(scope_name_); 1911 } 1912 1913 // Print parameters, if any. 1914 Variable* function = nullptr; 1915 if (is_function_scope()) { 1916 AsDeclarationScope()->PrintParameters(); 1917 function = AsDeclarationScope()->function_var(); 1918 } 1919 1920 PrintF(" { // (%p) (%d, %d)\n", reinterpret_cast<void*>(this), 1921 start_position(), end_position()); 1922 if (is_hidden()) { 1923 Indent(n1, "// is hidden\n"); 1924 } 1925 1926 // Function name, if any (named function literals, only). 1927 if (function != nullptr) { 1928 Indent(n1, "// (local) function name: "); 1929 PrintName(function->raw_name()); 1930 PrintF("\n"); 1931 } 1932 1933 // Scope info. 1934 if (is_strict(language_mode())) { 1935 Indent(n1, "// strict mode scope\n"); 1936 } 1937#if V8_ENABLE_WEBASSEMBLY 1938 if (IsAsmModule()) Indent(n1, "// scope is an asm module\n"); 1939#endif // V8_ENABLE_WEBASSEMBLY 1940 if (is_declaration_scope() && 1941 AsDeclarationScope()->sloppy_eval_can_extend_vars()) { 1942 Indent(n1, "// scope calls sloppy 'eval'\n"); 1943 } 1944 if (private_name_lookup_skips_outer_class()) { 1945 Indent(n1, "// scope skips outer class for #-names\n"); 1946 } 1947 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 1948 if (is_declaration_scope()) { 1949 DeclarationScope* scope = AsDeclarationScope(); 1950 if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n"); 1951 if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n"); 1952 if (scope->needs_private_name_context_chain_recalc()) { 1953 Indent(n1, "// needs #-name context chain recalc\n"); 1954 } 1955 Indent(n1, "// "); 1956 PrintF("%s\n", FunctionKind2String(scope->function_kind())); 1957 if (scope->class_scope_has_private_brand()) { 1958 Indent(n1, "// class scope has private brand\n"); 1959 } 1960 } 1961 if (num_stack_slots_ > 0) { 1962 Indent(n1, "// "); 1963 PrintF("%d stack slots\n", num_stack_slots_); 1964 } 1965 if (num_heap_slots_ > 0) { 1966 Indent(n1, "// "); 1967 PrintF("%d heap slots\n", num_heap_slots_); 1968 } 1969 1970 // Print locals. 1971 if (function != nullptr) { 1972 Indent(n1, "// function var:\n"); 1973 PrintVar(n1, function); 1974 } 1975 1976 // Print temporaries. 1977 { 1978 bool printed_header = false; 1979 for (Variable* local : locals_) { 1980 if (local->mode() != VariableMode::kTemporary) continue; 1981 if (!printed_header) { 1982 printed_header = true; 1983 Indent(n1, "// temporary vars:\n"); 1984 } 1985 PrintVar(n1, local); 1986 } 1987 } 1988 1989 if (variables_.occupancy() > 0) { 1990 PrintMap(n1, "// local vars:\n", &variables_, true, function); 1991 PrintMap(n1, "// dynamic vars:\n", &variables_, false, function); 1992 } 1993 1994 if (is_class_scope()) { 1995 ClassScope* class_scope = AsClassScope(); 1996 if (class_scope->GetRareData() != nullptr) { 1997 PrintMap(n1, "// private name vars:\n", 1998 &(class_scope->GetRareData()->private_name_map), true, function); 1999 Variable* brand = class_scope->brand(); 2000 if (brand != nullptr) { 2001 Indent(n1, "// brand var:\n"); 2002 PrintVar(n1, brand); 2003 } 2004 } 2005 if (class_scope->class_variable() != nullptr) { 2006 Indent(n1, "// class var"); 2007 PrintF("%s%s:\n", 2008 class_scope->class_variable()->is_used() ? ", used" : ", unused", 2009 class_scope->should_save_class_variable_index() 2010 ? ", index saved" 2011 : ", index not saved"); 2012 PrintVar(n1, class_scope->class_variable()); 2013 } 2014 } 2015 2016 // Print inner scopes (disable by providing negative n). 2017 if (n >= 0) { 2018 for (Scope* scope = inner_scope_; scope != nullptr; 2019 scope = scope->sibling_) { 2020 PrintF("\n"); 2021 scope->Print(n1); 2022 } 2023 } 2024 2025 Indent(n0, "}\n"); 2026} 2027 2028void Scope::CheckScopePositions() { 2029 this->ForEach([](Scope* scope) { 2030 // Visible leaf scopes must have real positions. 2031 if (!scope->is_hidden() && scope->inner_scope_ == nullptr) { 2032 DCHECK_NE(kNoSourcePosition, scope->start_position()); 2033 DCHECK_NE(kNoSourcePosition, scope->end_position()); 2034 } 2035 return Iteration::kDescend; 2036 }); 2037} 2038 2039void Scope::CheckZones() { 2040 DCHECK(!needs_migration_); 2041 this->ForEach([](Scope* scope) { 2042 if (WasLazilyParsed(scope)) { 2043 DCHECK_NULL(scope->zone()); 2044 DCHECK_NULL(scope->inner_scope_); 2045 return Iteration::kContinue; 2046 } 2047 return Iteration::kDescend; 2048 }); 2049} 2050#endif // DEBUG 2051 2052Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { 2053 // Declare a new non-local. 2054 DCHECK(IsDynamicVariableMode(mode)); 2055 bool was_added; 2056 Variable* var = variables_.Declare(zone(), this, name, mode, NORMAL_VARIABLE, 2057 kCreatedInitialized, kNotAssigned, 2058 IsStaticFlag::kNotStatic, &was_added); 2059 // Allocate it by giving it a dynamic lookup. 2060 var->AllocateTo(VariableLocation::LOOKUP, -1); 2061 return var; 2062} 2063 2064// static 2065template <Scope::ScopeLookupMode mode> 2066Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope, 2067 Scope* outer_scope_end, Scope* cache_scope, 2068 bool force_context_allocation) { 2069 // If we have already passed the cache scope in earlier recursions, we should 2070 // first quickly check if the current scope uses the cache scope before 2071 // continuing. 2072 if (mode == kDeserializedScope && 2073 scope->deserialized_scope_uses_external_cache()) { 2074 Variable* var = cache_scope->variables_.Lookup(proxy->raw_name()); 2075 if (var != nullptr) return var; 2076 } 2077 2078 while (true) { 2079 DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_); 2080 // Short-cut: whenever we find a debug-evaluate scope, just look everything 2081 // up dynamically. Debug-evaluate doesn't properly create scope info for the 2082 // lookups it does. It may not have a valid 'this' declaration, and anything 2083 // accessed through debug-evaluate might invalidly resolve to 2084 // stack-allocated variables. 2085 // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for 2086 // the scopes in which it's evaluating. 2087 if (mode == kDeserializedScope && 2088 V8_UNLIKELY(scope->is_debug_evaluate_scope_)) { 2089 DCHECK(scope->deserialized_scope_uses_external_cache() || 2090 scope == cache_scope); 2091 return cache_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic); 2092 } 2093 2094 // Try to find the variable in this scope. 2095 Variable* var; 2096 if (mode == kParsedScope) { 2097 var = scope->LookupLocal(proxy->raw_name()); 2098 } else { 2099 DCHECK_EQ(mode, kDeserializedScope); 2100 bool external_cache = scope->deserialized_scope_uses_external_cache(); 2101 if (!external_cache) { 2102 // Check the cache on each deserialized scope, up to the main cache 2103 // scope when we get to it (we may still have deserialized scopes 2104 // in-between the initial and cache scopes so we can't just check the 2105 // cache before the loop). 2106 var = scope->variables_.Lookup(proxy->raw_name()); 2107 if (var != nullptr) return var; 2108 } 2109 var = scope->LookupInScopeInfo(proxy->raw_name(), 2110 external_cache ? cache_scope : scope); 2111 } 2112 2113 // We found a variable and we are done. (Even if there is an 'eval' in this 2114 // scope which introduces the same variable again, the resulting variable 2115 // remains the same.) 2116 // 2117 // For sloppy eval though, we skip dynamic variable to avoid resolving to a 2118 // variable when the variable and proxy are in the same eval execution. The 2119 // variable is not available on subsequent lazy executions of functions in 2120 // the eval, so this avoids inner functions from looking up different 2121 // variables during eager and lazy compilation. 2122 // 2123 // TODO(leszeks): Maybe we want to restrict this to e.g. lookups of a proxy 2124 // living in a different scope to the current one, or some other 2125 // optimisation. 2126 if (var != nullptr && 2127 !(scope->is_eval_scope() && var->mode() == VariableMode::kDynamic)) { 2128 if (mode == kParsedScope && force_context_allocation && 2129 !var->is_dynamic()) { 2130 var->ForceContextAllocation(); 2131 } 2132 return var; 2133 } 2134 2135 if (scope->outer_scope_ == outer_scope_end) break; 2136 2137 DCHECK(!scope->is_script_scope()); 2138 if (V8_UNLIKELY(scope->is_with_scope())) { 2139 return LookupWith(proxy, scope, outer_scope_end, cache_scope, 2140 force_context_allocation); 2141 } 2142 if (V8_UNLIKELY( 2143 scope->is_declaration_scope() && 2144 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars())) { 2145 return LookupSloppyEval(proxy, scope, outer_scope_end, cache_scope, 2146 force_context_allocation); 2147 } 2148 2149 force_context_allocation |= scope->is_function_scope(); 2150 scope = scope->outer_scope_; 2151 2152 // TODO(verwaest): Separate through AnalyzePartially. 2153 if (mode == kParsedScope && !scope->scope_info_.is_null()) { 2154 DCHECK_NULL(cache_scope); 2155 cache_scope = scope->GetNonEvalDeclarationScope(); 2156 return Lookup<kDeserializedScope>(proxy, scope, outer_scope_end, 2157 cache_scope); 2158 } 2159 } 2160 2161 // We may just be trying to find all free variables. In that case, don't 2162 // declare them in the outer scope. 2163 // TODO(marja): Separate Lookup for preparsed scopes better. 2164 if (mode == kParsedScope && !scope->is_script_scope()) { 2165 return nullptr; 2166 } 2167 2168 // No binding has been found. Declare a variable on the global object. 2169 return scope->AsDeclarationScope()->DeclareDynamicGlobal( 2170 proxy->raw_name(), NORMAL_VARIABLE, 2171 mode == kDeserializedScope ? cache_scope : scope); 2172} 2173 2174template Variable* Scope::Lookup<Scope::kParsedScope>( 2175 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end, 2176 Scope* cache_scope, bool force_context_allocation); 2177template Variable* Scope::Lookup<Scope::kDeserializedScope>( 2178 VariableProxy* proxy, Scope* scope, Scope* outer_scope_end, 2179 Scope* cache_scope, bool force_context_allocation); 2180 2181Variable* Scope::LookupWith(VariableProxy* proxy, Scope* scope, 2182 Scope* outer_scope_end, Scope* cache_scope, 2183 bool force_context_allocation) { 2184 DCHECK(scope->is_with_scope()); 2185 2186 Variable* var = 2187 scope->outer_scope_->scope_info_.is_null() 2188 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end, 2189 nullptr, force_context_allocation) 2190 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_, 2191 outer_scope_end, cache_scope); 2192 2193 if (var == nullptr) return var; 2194 2195 // The current scope is a with scope, so the variable binding can not be 2196 // statically resolved. However, note that it was necessary to do a lookup 2197 // in the outer scope anyway, because if a binding exists in an outer 2198 // scope, the associated variable has to be marked as potentially being 2199 // accessed from inside of an inner with scope (the property may not be in 2200 // the 'with' object). 2201 if (!var->is_dynamic() && var->IsUnallocated()) { 2202 DCHECK(!scope->already_resolved_); 2203 var->set_is_used(); 2204 var->ForceContextAllocation(); 2205 if (proxy->is_assigned()) var->SetMaybeAssigned(); 2206 } 2207 Scope* target_scope; 2208 if (scope->deserialized_scope_uses_external_cache()) { 2209 DCHECK_NOT_NULL(cache_scope); 2210 cache_scope->variables_.Remove(var); 2211 target_scope = cache_scope; 2212 } else { 2213 target_scope = scope; 2214 } 2215 Variable* dynamic = 2216 target_scope->NonLocal(proxy->raw_name(), VariableMode::kDynamic); 2217 dynamic->set_local_if_not_shadowed(var); 2218 return dynamic; 2219} 2220 2221Variable* Scope::LookupSloppyEval(VariableProxy* proxy, Scope* scope, 2222 Scope* outer_scope_end, Scope* cache_scope, 2223 bool force_context_allocation) { 2224 DCHECK(scope->is_declaration_scope() && 2225 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()); 2226 2227 // If we're compiling eval, it's possible that the outer scope is the first 2228 // ScopeInfo-backed scope. We use the next declaration scope as the cache for 2229 // this case, to avoid complexity around sloppy block function hoisting and 2230 // conflict detection through catch scopes in the eval. 2231 Scope* entry_cache = cache_scope == nullptr 2232 ? scope->outer_scope()->GetNonEvalDeclarationScope() 2233 : cache_scope; 2234 Variable* var = 2235 scope->outer_scope_->scope_info_.is_null() 2236 ? Lookup<kParsedScope>(proxy, scope->outer_scope_, outer_scope_end, 2237 nullptr, force_context_allocation) 2238 : Lookup<kDeserializedScope>(proxy, scope->outer_scope_, 2239 outer_scope_end, entry_cache); 2240 if (var == nullptr) return var; 2241 2242 // We may not want to use the cache scope, change it back to the given scope 2243 // if necessary. 2244 if (!scope->deserialized_scope_uses_external_cache()) { 2245 // For a deserialized scope, we'll be replacing the cache_scope. 2246 DCHECK_IMPLIES(!scope->scope_info_.is_null(), cache_scope != nullptr); 2247 cache_scope = scope; 2248 } 2249 2250 // A variable binding may have been found in an outer scope, but the current 2251 // scope makes a sloppy 'eval' call, so the found variable may not be the 2252 // correct one (the 'eval' may introduce a binding with the same name). In 2253 // that case, change the lookup result to reflect this situation. Only 2254 // scopes that can host var bindings (declaration scopes) need be considered 2255 // here (this excludes block and catch scopes), and variable lookups at 2256 // script scope are always dynamic. 2257 if (var->IsGlobalObjectProperty()) { 2258 Scope* target = cache_scope == nullptr ? scope : cache_scope; 2259 var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicGlobal); 2260 } 2261 2262 if (var->is_dynamic()) return var; 2263 2264 Variable* invalidated = var; 2265 if (cache_scope != nullptr) cache_scope->variables_.Remove(invalidated); 2266 2267 Scope* target = cache_scope == nullptr ? scope : cache_scope; 2268 var = target->NonLocal(proxy->raw_name(), VariableMode::kDynamicLocal); 2269 var->set_local_if_not_shadowed(invalidated); 2270 2271 return var; 2272} 2273 2274void Scope::ResolveVariable(VariableProxy* proxy) { 2275 DCHECK(!proxy->is_resolved()); 2276 Variable* var = Lookup<kParsedScope>(proxy, this, nullptr); 2277 DCHECK_NOT_NULL(var); 2278 ResolveTo(proxy, var); 2279} 2280 2281namespace { 2282 2283void SetNeedsHoleCheck(Variable* var, VariableProxy* proxy) { 2284 proxy->set_needs_hole_check(); 2285 var->ForceHoleInitialization(); 2286} 2287 2288void UpdateNeedsHoleCheck(Variable* var, VariableProxy* proxy, Scope* scope) { 2289 if (var->mode() == VariableMode::kDynamicLocal) { 2290 // Dynamically introduced variables never need a hole check (since they're 2291 // VariableMode::kVar bindings, either from var or function declarations), 2292 // but the variable they shadow might need a hole check, which we want to do 2293 // if we decide that no shadowing variable was dynamically introoduced. 2294 DCHECK_EQ(kCreatedInitialized, var->initialization_flag()); 2295 return UpdateNeedsHoleCheck(var->local_if_not_shadowed(), proxy, scope); 2296 } 2297 2298 if (var->initialization_flag() == kCreatedInitialized) return; 2299 2300 // It's impossible to eliminate module import hole checks here, because it's 2301 // unknown at compilation time whether the binding referred to in the 2302 // exporting module itself requires hole checks. 2303 if (var->location() == VariableLocation::MODULE && !var->IsExport()) { 2304 return SetNeedsHoleCheck(var, proxy); 2305 } 2306 2307 // Check if the binding really needs an initialization check. The check 2308 // can be skipped in the following situation: we have a VariableMode::kLet or 2309 // VariableMode::kConst binding, both the Variable and the VariableProxy have 2310 // the same declaration scope (i.e. they are both in global code, in the same 2311 // function or in the same eval code), the VariableProxy is in the source 2312 // physically located after the initializer of the variable, and that the 2313 // initializer cannot be skipped due to a nonlinear scope. 2314 // 2315 // The condition on the closure scopes is a conservative check for 2316 // nested functions that access a binding and are called before the 2317 // binding is initialized: 2318 // function() { f(); let x = 1; function f() { x = 2; } } 2319 // 2320 // The check cannot be skipped on non-linear scopes, namely switch 2321 // scopes, to ensure tests are done in cases like the following: 2322 // switch (1) { case 0: let x = 2; case 1: f(x); } 2323 // The scope of the variable needs to be checked, in case the use is 2324 // in a sub-block which may be linear. 2325 if (var->scope()->GetClosureScope() != scope->GetClosureScope()) { 2326 return SetNeedsHoleCheck(var, proxy); 2327 } 2328 2329 // We should always have valid source positions. 2330 DCHECK_NE(var->initializer_position(), kNoSourcePosition); 2331 DCHECK_NE(proxy->position(), kNoSourcePosition); 2332 2333 if (var->scope()->is_nonlinear() || 2334 var->initializer_position() >= proxy->position()) { 2335 return SetNeedsHoleCheck(var, proxy); 2336 } 2337} 2338 2339} // anonymous namespace 2340 2341void Scope::ResolveTo(VariableProxy* proxy, Variable* var) { 2342 DCHECK_NOT_NULL(var); 2343 UpdateNeedsHoleCheck(var, proxy, this); 2344 proxy->BindTo(var); 2345} 2346 2347void Scope::ResolvePreparsedVariable(VariableProxy* proxy, Scope* scope, 2348 Scope* end) { 2349 // Resolve the variable in all parsed scopes to force context allocation. 2350 for (; scope != end; scope = scope->outer_scope_) { 2351 Variable* var = scope->LookupLocal(proxy->raw_name()); 2352 if (var != nullptr) { 2353 var->set_is_used(); 2354 if (!var->is_dynamic()) { 2355 var->ForceContextAllocation(); 2356 if (proxy->is_assigned()) var->SetMaybeAssigned(); 2357 return; 2358 } 2359 } 2360 } 2361} 2362 2363bool Scope::ResolveVariablesRecursively(Scope* end) { 2364 // Lazy parsed declaration scopes are already partially analyzed. If there are 2365 // unresolved references remaining, they just need to be resolved in outer 2366 // scopes. 2367 if (WasLazilyParsed(this)) { 2368 DCHECK_EQ(variables_.occupancy(), 0); 2369 // Resolve in all parsed scopes except for the script scope. 2370 if (!end->is_script_scope()) end = end->outer_scope(); 2371 2372 for (VariableProxy* proxy : unresolved_list_) { 2373 ResolvePreparsedVariable(proxy, outer_scope(), end); 2374 } 2375 } else { 2376 // Resolve unresolved variables for this scope. 2377 for (VariableProxy* proxy : unresolved_list_) { 2378 ResolveVariable(proxy); 2379 } 2380 2381 // Resolve unresolved variables for inner scopes. 2382 for (Scope* scope = inner_scope_; scope != nullptr; 2383 scope = scope->sibling_) { 2384 if (!scope->ResolveVariablesRecursively(end)) return false; 2385 } 2386 } 2387 return true; 2388} 2389 2390bool Scope::MustAllocate(Variable* var) { 2391 DCHECK(var->location() != VariableLocation::MODULE); 2392 // Give var a read/write use if there is a chance it might be accessed 2393 // via an eval() call. This is only possible if the variable has a 2394 // visible name. 2395 if (!var->raw_name()->IsEmpty() && 2396 (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) { 2397 var->set_is_used(); 2398 if (inner_scope_calls_eval_ && !var->is_this()) var->SetMaybeAssigned(); 2399 } 2400 DCHECK(!var->has_forced_context_allocation() || var->is_used()); 2401 // Global variables do not need to be allocated. 2402 return !var->IsGlobalObjectProperty() && var->is_used(); 2403} 2404 2405 2406bool Scope::MustAllocateInContext(Variable* var) { 2407 // If var is accessed from an inner scope, or if there is a possibility 2408 // that it might be accessed from the current or an inner scope (through 2409 // an eval() call or a runtime with lookup), it must be allocated in the 2410 // context. 2411 // 2412 // Temporary variables are always stack-allocated. Catch-bound variables are 2413 // always context-allocated. 2414 VariableMode mode = var->mode(); 2415 if (mode == VariableMode::kTemporary) return false; 2416 if (is_catch_scope()) return true; 2417 if (is_script_scope() || is_eval_scope()) { 2418 if (IsLexicalVariableMode(mode)) { 2419 return true; 2420 } 2421 } 2422 return var->has_forced_context_allocation() || inner_scope_calls_eval_; 2423} 2424 2425void Scope::AllocateStackSlot(Variable* var) { 2426 if (is_block_scope()) { 2427 outer_scope()->GetDeclarationScope()->AllocateStackSlot(var); 2428 } else { 2429 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); 2430 } 2431} 2432 2433 2434void Scope::AllocateHeapSlot(Variable* var) { 2435 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++); 2436} 2437 2438void DeclarationScope::AllocateParameterLocals() { 2439 DCHECK(is_function_scope()); 2440 2441 bool has_mapped_arguments = false; 2442 if (arguments_ != nullptr) { 2443 DCHECK(!is_arrow_scope()); 2444 if (MustAllocate(arguments_) && !has_arguments_parameter_) { 2445 // 'arguments' is used and does not refer to a function 2446 // parameter of the same name. If the arguments object 2447 // aliases formal parameters, we conservatively allocate 2448 // them specially in the loop below. 2449 has_mapped_arguments = 2450 GetArgumentsType() == CreateArgumentsType::kMappedArguments; 2451 } else { 2452 // 'arguments' is unused. Tell the code generator that it does not need to 2453 // allocate the arguments object by nulling out arguments_. 2454 arguments_ = nullptr; 2455 } 2456 } 2457 2458 // The same parameter may occur multiple times in the parameters_ list. 2459 // If it does, and if it is not copied into the context object, it must 2460 // receive the highest parameter index for that parameter; thus iteration 2461 // order is relevant! 2462 for (int i = num_parameters() - 1; i >= 0; --i) { 2463 Variable* var = params_[i]; 2464 DCHECK_NOT_NULL(var); 2465 DCHECK(!has_rest_ || var != rest_parameter()); 2466 DCHECK_EQ(this, var->scope()); 2467 if (has_mapped_arguments) { 2468 var->set_is_used(); 2469 var->SetMaybeAssigned(); 2470 var->ForceContextAllocation(); 2471 } 2472 AllocateParameter(var, i); 2473 } 2474} 2475 2476void DeclarationScope::AllocateParameter(Variable* var, int index) { 2477 if (!MustAllocate(var)) return; 2478 if (has_forced_context_allocation_for_parameters() || 2479 MustAllocateInContext(var)) { 2480 DCHECK(var->IsUnallocated() || var->IsContextSlot()); 2481 if (var->IsUnallocated()) AllocateHeapSlot(var); 2482 } else { 2483 DCHECK(var->IsUnallocated() || var->IsParameter()); 2484 if (var->IsUnallocated()) { 2485 var->AllocateTo(VariableLocation::PARAMETER, index); 2486 } 2487 } 2488} 2489 2490void DeclarationScope::AllocateReceiver() { 2491 if (!has_this_declaration()) return; 2492 DCHECK_NOT_NULL(receiver()); 2493 DCHECK_EQ(receiver()->scope(), this); 2494 AllocateParameter(receiver(), -1); 2495} 2496 2497void Scope::AllocateNonParameterLocal(Variable* var) { 2498 DCHECK_EQ(var->scope(), this); 2499 if (var->IsUnallocated() && MustAllocate(var)) { 2500 if (MustAllocateInContext(var)) { 2501 AllocateHeapSlot(var); 2502 DCHECK_IMPLIES(is_catch_scope(), 2503 var->index() == Context::THROWN_OBJECT_INDEX); 2504 } else { 2505 AllocateStackSlot(var); 2506 } 2507 } 2508} 2509 2510void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() { 2511 if (is_declaration_scope() && AsDeclarationScope()->is_arrow_scope()) { 2512 // In arrow functions, allocate non-temporaries first and then all the 2513 // temporaries to make the local variable ordering stable when reparsing to 2514 // collect source positions. 2515 for (Variable* local : locals_) { 2516 if (local->mode() != VariableMode::kTemporary) 2517 AllocateNonParameterLocal(local); 2518 } 2519 2520 for (Variable* local : locals_) { 2521 if (local->mode() == VariableMode::kTemporary) 2522 AllocateNonParameterLocal(local); 2523 } 2524 } else { 2525 for (Variable* local : locals_) { 2526 AllocateNonParameterLocal(local); 2527 } 2528 } 2529 2530 if (is_declaration_scope()) { 2531 AsDeclarationScope()->AllocateLocals(); 2532 } 2533} 2534 2535void DeclarationScope::AllocateLocals() { 2536 // For now, function_ must be allocated at the very end. If it gets 2537 // allocated in the context, it must be the last slot in the context, 2538 // because of the current ScopeInfo implementation (see 2539 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 2540 if (function_ != nullptr && MustAllocate(function_)) { 2541 AllocateNonParameterLocal(function_); 2542 } else { 2543 function_ = nullptr; 2544 } 2545 2546 DCHECK(!has_rest_ || !MustAllocate(rest_parameter()) || 2547 !rest_parameter()->IsUnallocated()); 2548 2549 if (new_target_ != nullptr && !MustAllocate(new_target_)) { 2550 new_target_ = nullptr; 2551 } 2552 2553 NullifyRareVariableIf(RareVariable::kThisFunction, 2554 [=](Variable* var) { return !MustAllocate(var); }); 2555} 2556 2557void ModuleScope::AllocateModuleVariables() { 2558 for (const auto& it : module()->regular_imports()) { 2559 Variable* var = LookupLocal(it.first); 2560 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index); 2561 DCHECK(!var->IsExport()); 2562 } 2563 2564 for (const auto& it : module()->regular_exports()) { 2565 Variable* var = LookupLocal(it.first); 2566 var->AllocateTo(VariableLocation::MODULE, it.second->cell_index); 2567 DCHECK(var->IsExport()); 2568 } 2569} 2570 2571void Scope::AllocateVariablesRecursively() { 2572 this->ForEach([](Scope* scope) -> Iteration { 2573 DCHECK(!scope->already_resolved_); 2574 if (WasLazilyParsed(scope)) return Iteration::kContinue; 2575 if (scope->sloppy_eval_can_extend_vars_) { 2576 scope->num_heap_slots_ = Context::MIN_CONTEXT_EXTENDED_SLOTS; 2577 } 2578 DCHECK_EQ(scope->ContextHeaderLength(), scope->num_heap_slots_); 2579 2580 // Allocate variables for this scope. 2581 // Parameters must be allocated first, if any. 2582 if (scope->is_declaration_scope()) { 2583 scope->AsDeclarationScope()->AllocateReceiver(); 2584 if (scope->is_function_scope()) { 2585 scope->AsDeclarationScope()->AllocateParameterLocals(); 2586 } 2587 } 2588 scope->AllocateNonParameterLocalsAndDeclaredGlobals(); 2589 2590 // Force allocation of a context for this scope if necessary. For a 'with' 2591 // scope and for a function scope that makes an 'eval' call we need a 2592 // context, even if no local variables were statically allocated in the 2593 // scope. Likewise for modules and function scopes representing asm.js 2594 // modules. Also force a context, if the scope is stricter than the outer 2595 // scope. 2596 bool must_have_context = 2597 scope->is_with_scope() || scope->is_module_scope() || 2598#if V8_ENABLE_WEBASSEMBLY 2599 scope->IsAsmModule() || 2600#endif // V8_ENABLE_WEBASSEMBLY 2601 scope->ForceContextForLanguageMode() || 2602 (scope->is_function_scope() && 2603 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()) || 2604 (scope->is_block_scope() && scope->is_declaration_scope() && 2605 scope->AsDeclarationScope()->sloppy_eval_can_extend_vars()); 2606 2607 // If we didn't allocate any locals in the local context, then we only 2608 // need the minimal number of slots if we must have a context. 2609 if (scope->num_heap_slots_ == scope->ContextHeaderLength() && 2610 !must_have_context) { 2611 scope->num_heap_slots_ = 0; 2612 } 2613 2614 // Allocation done. 2615 DCHECK(scope->num_heap_slots_ == 0 || 2616 scope->num_heap_slots_ >= scope->ContextHeaderLength()); 2617 return Iteration::kDescend; 2618 }); 2619} 2620 2621template <typename IsolateT> 2622void Scope::AllocateScopeInfosRecursively(IsolateT* isolate, 2623 MaybeHandle<ScopeInfo> outer_scope) { 2624 DCHECK(scope_info_.is_null()); 2625 MaybeHandle<ScopeInfo> next_outer_scope = outer_scope; 2626 2627 if (NeedsScopeInfo()) { 2628 scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope); 2629 // The ScopeInfo chain should mirror the context chain, so we only link to 2630 // the next outer scope that needs a context. 2631 if (NeedsContext()) next_outer_scope = scope_info_; 2632 } 2633 2634 // Allocate ScopeInfos for inner scopes. 2635 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 2636 if (!scope->is_function_scope() || 2637 scope->AsDeclarationScope()->ShouldEagerCompile()) { 2638 scope->AllocateScopeInfosRecursively(isolate, next_outer_scope); 2639 } 2640 } 2641} 2642 2643template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope:: 2644 AllocateScopeInfosRecursively<Isolate>(Isolate* isolate, 2645 MaybeHandle<ScopeInfo> outer_scope); 2646template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) void Scope:: 2647 AllocateScopeInfosRecursively<LocalIsolate>( 2648 LocalIsolate* isolate, MaybeHandle<ScopeInfo> outer_scope); 2649 2650void DeclarationScope::RecalcPrivateNameContextChain() { 2651 // The outermost scope in a class heritage expression is marked to skip the 2652 // class scope during private name resolution. It is possible, however, that 2653 // either the class scope won't require a Context and ScopeInfo, or the 2654 // outermost scope in the heritage position won't. Simply copying the bit from 2655 // full parse into the ScopeInfo will break lazy compilation. In the former 2656 // case the scope that is marked to skip its outer scope will incorrectly skip 2657 // a different class scope than the one we intended to skip. In the latter 2658 // case variables resolved through an inner scope will incorrectly check the 2659 // class scope since we lost the skip bit from the outermost heritage scope. 2660 // 2661 // This method fixes both cases by, in outermost to innermost order, copying 2662 // the value of the skip bit from outer scopes that don't require a Context. 2663 DCHECK(needs_private_name_context_chain_recalc_); 2664 this->ForEach([](Scope* scope) { 2665 Scope* outer = scope->outer_scope(); 2666 if (!outer) return Iteration::kDescend; 2667 if (!outer->NeedsContext()) { 2668 scope->private_name_lookup_skips_outer_class_ = 2669 outer->private_name_lookup_skips_outer_class(); 2670 } 2671 if (!scope->is_function_scope() || 2672 scope->AsDeclarationScope()->ShouldEagerCompile()) { 2673 return Iteration::kDescend; 2674 } 2675 return Iteration::kContinue; 2676 }); 2677} 2678 2679void DeclarationScope::RecordNeedsPrivateNameContextChainRecalc() { 2680 DCHECK_EQ(GetClosureScope(), this); 2681 DeclarationScope* scope; 2682 for (scope = this; scope != nullptr; 2683 scope = scope->outer_scope() != nullptr 2684 ? scope->outer_scope()->GetClosureScope() 2685 : nullptr) { 2686 if (scope->needs_private_name_context_chain_recalc_) return; 2687 scope->needs_private_name_context_chain_recalc_ = true; 2688 } 2689} 2690 2691// static 2692template <typename IsolateT> 2693void DeclarationScope::AllocateScopeInfos(ParseInfo* info, IsolateT* isolate) { 2694 DeclarationScope* scope = info->literal()->scope(); 2695 2696 // No one else should have allocated a scope info for this scope yet. 2697 DCHECK(scope->scope_info_.is_null()); 2698 2699 MaybeHandle<ScopeInfo> outer_scope; 2700 if (scope->outer_scope_ != nullptr) { 2701 DCHECK((std::is_same<Isolate, v8::internal::Isolate>::value)); 2702 outer_scope = scope->outer_scope_->scope_info_; 2703 } 2704 2705 if (scope->needs_private_name_context_chain_recalc()) { 2706 scope->RecalcPrivateNameContextChain(); 2707 } 2708 scope->AllocateScopeInfosRecursively(isolate, outer_scope); 2709 2710 // The debugger expects all shared function infos to contain a scope info. 2711 // Since the top-most scope will end up in a shared function info, make sure 2712 // it has one, even if it doesn't need a scope info. 2713 // TODO(yangguo): Remove this requirement. 2714 if (scope->scope_info_.is_null()) { 2715 scope->scope_info_ = 2716 ScopeInfo::Create(isolate, scope->zone(), scope, outer_scope); 2717 } 2718 2719 // Ensuring that the outer script scope has a scope info avoids having 2720 // special case for native contexts vs other contexts. 2721 if (info->script_scope() && info->script_scope()->scope_info_.is_null()) { 2722 info->script_scope()->scope_info_ = isolate->factory()->empty_scope_info(); 2723 } 2724} 2725 2726template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos( 2727 ParseInfo* info, Isolate* isolate); 2728template V8_EXPORT_PRIVATE void DeclarationScope::AllocateScopeInfos( 2729 ParseInfo* info, LocalIsolate* isolate); 2730 2731int Scope::ContextLocalCount() const { 2732 if (num_heap_slots() == 0) return 0; 2733 Variable* function = 2734 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; 2735 bool is_function_var_in_context = 2736 function != nullptr && function->IsContextSlot(); 2737 return num_heap_slots() - ContextHeaderLength() - 2738 (is_function_var_in_context ? 1 : 0); 2739} 2740 2741VariableProxy* Scope::NewHomeObjectVariableProxy(AstNodeFactory* factory, 2742 const AstRawString* name, 2743 int start_pos) { 2744 // VariableProxies of the home object cannot be resolved like a normal 2745 // variable. Consider the case of a super.property usage in heritage position: 2746 // 2747 // class C extends super.foo { m() { super.bar(); } } 2748 // 2749 // The super.foo property access is logically nested under C's class scope, 2750 // which also has a home object due to its own method m's usage of 2751 // super.bar(). However, super.foo must resolve super in C's outer scope. 2752 // 2753 // Because of the above, home object VariableProxies are always made directly 2754 // on the Scope that needs the home object instead of the innermost scope. 2755 DCHECK(needs_home_object()); 2756 if (!scope_info_.is_null()) { 2757 // This is a lazy compile, so the home object's context slot is already 2758 // known. 2759 Variable* home_object = variables_.Lookup(name); 2760 if (home_object == nullptr) { 2761 VariableLookupResult lookup_result; 2762 int index = scope_info_->ContextSlotIndex(name->string(), &lookup_result); 2763 DCHECK_GE(index, 0); 2764 bool was_added; 2765 home_object = variables_.Declare(zone(), this, name, lookup_result.mode, 2766 NORMAL_VARIABLE, lookup_result.init_flag, 2767 lookup_result.maybe_assigned_flag, 2768 IsStaticFlag::kNotStatic, &was_added); 2769 DCHECK(was_added); 2770 home_object->AllocateTo(VariableLocation::CONTEXT, index); 2771 } 2772 return factory->NewVariableProxy(home_object, start_pos); 2773 } 2774 // This is not a lazy compile. Add the unresolved home object VariableProxy to 2775 // the unresolved list of the home object scope, which is not necessarily the 2776 // innermost scope. 2777 VariableProxy* proxy = 2778 factory->NewVariableProxy(name, NORMAL_VARIABLE, start_pos); 2779 AddUnresolved(proxy); 2780 return proxy; 2781} 2782 2783bool IsComplementaryAccessorPair(VariableMode a, VariableMode b) { 2784 switch (a) { 2785 case VariableMode::kPrivateGetterOnly: 2786 return b == VariableMode::kPrivateSetterOnly; 2787 case VariableMode::kPrivateSetterOnly: 2788 return b == VariableMode::kPrivateGetterOnly; 2789 default: 2790 return false; 2791 } 2792} 2793 2794void ClassScope::FinalizeReparsedClassScope( 2795 Isolate* isolate, MaybeHandle<ScopeInfo> maybe_scope_info, 2796 AstValueFactory* ast_value_factory, bool needs_allocation_fixup) { 2797 // Set this bit so that DelcarationScope::Analyze recognizes 2798 // the reparsed instance member initializer scope. 2799#ifdef DEBUG 2800 is_reparsed_class_scope_ = true; 2801#endif 2802 2803 if (!needs_allocation_fixup) { 2804 return; 2805 } 2806 2807 // Restore variable allocation results for context-allocated variables in 2808 // the class scope from ScopeInfo, so that we don't need to run 2809 // resolution and allocation on these variables again when generating 2810 // code for the initializer function. 2811 DCHECK(!maybe_scope_info.is_null()); 2812 Handle<ScopeInfo> scope_info = maybe_scope_info.ToHandleChecked(); 2813 DCHECK_EQ(scope_info->scope_type(), CLASS_SCOPE); 2814 DCHECK_EQ(scope_info->StartPosition(), start_position_); 2815 2816 int context_header_length = scope_info->ContextHeaderLength(); 2817 DisallowGarbageCollection no_gc; 2818 for (auto it : ScopeInfo::IterateLocalNames(scope_info)) { 2819 int slot_index = context_header_length + it->index(); 2820 DCHECK_LT(slot_index, scope_info->ContextLength()); 2821 2822 const AstRawString* string = ast_value_factory->GetString( 2823 it->name(), SharedStringAccessGuardIfNeeded(isolate)); 2824 Variable* var = string->IsPrivateName() ? LookupLocalPrivateName(string) 2825 : LookupLocal(string); 2826 DCHECK_NOT_NULL(var); 2827 var->AllocateTo(VariableLocation::CONTEXT, slot_index); 2828 } 2829 scope_info_ = scope_info; 2830} 2831 2832Variable* ClassScope::DeclarePrivateName(const AstRawString* name, 2833 VariableMode mode, 2834 IsStaticFlag is_static_flag, 2835 bool* was_added) { 2836 Variable* result = EnsureRareData()->private_name_map.Declare( 2837 zone(), this, name, mode, NORMAL_VARIABLE, 2838 InitializationFlag::kNeedsInitialization, MaybeAssignedFlag::kNotAssigned, 2839 is_static_flag, was_added); 2840 if (*was_added) { 2841 locals_.Add(result); 2842 has_static_private_methods_ |= 2843 (result->is_static() && 2844 IsPrivateMethodOrAccessorVariableMode(result->mode())); 2845 } else if (IsComplementaryAccessorPair(result->mode(), mode) && 2846 result->is_static_flag() == is_static_flag) { 2847 *was_added = true; 2848 result->set_mode(VariableMode::kPrivateGetterAndSetter); 2849 } 2850 result->ForceContextAllocation(); 2851 return result; 2852} 2853 2854Variable* ClassScope::LookupLocalPrivateName(const AstRawString* name) { 2855 RareData* rare_data = GetRareData(); 2856 if (rare_data == nullptr) { 2857 return nullptr; 2858 } 2859 return rare_data->private_name_map.Lookup(name); 2860} 2861 2862UnresolvedList::Iterator ClassScope::GetUnresolvedPrivateNameTail() { 2863 RareData* rare_data = GetRareData(); 2864 if (rare_data == nullptr) { 2865 return UnresolvedList::Iterator(); 2866 } 2867 return rare_data->unresolved_private_names.end(); 2868} 2869 2870void ClassScope::ResetUnresolvedPrivateNameTail(UnresolvedList::Iterator tail) { 2871 RareData* rare_data = GetRareData(); 2872 if (rare_data == nullptr || 2873 rare_data->unresolved_private_names.end() == tail) { 2874 return; 2875 } 2876 2877 bool tail_is_empty = tail == UnresolvedList::Iterator(); 2878 if (tail_is_empty) { 2879 // If the saved tail is empty, the list used to be empty, so clear it. 2880 rare_data->unresolved_private_names.Clear(); 2881 } else { 2882 rare_data->unresolved_private_names.Rewind(tail); 2883 } 2884} 2885 2886void ClassScope::MigrateUnresolvedPrivateNameTail( 2887 AstNodeFactory* ast_node_factory, UnresolvedList::Iterator tail) { 2888 RareData* rare_data = GetRareData(); 2889 if (rare_data == nullptr || 2890 rare_data->unresolved_private_names.end() == tail) { 2891 return; 2892 } 2893 UnresolvedList migrated_names; 2894 2895 // If the saved tail is empty, the list used to be empty, so we should 2896 // migrate everything after the head. 2897 bool tail_is_empty = tail == UnresolvedList::Iterator(); 2898 UnresolvedList::Iterator it = 2899 tail_is_empty ? rare_data->unresolved_private_names.begin() : tail; 2900 2901 for (; it != rare_data->unresolved_private_names.end(); ++it) { 2902 VariableProxy* proxy = *it; 2903 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); 2904 migrated_names.Add(copy); 2905 } 2906 2907 // Replace with the migrated copies. 2908 if (tail_is_empty) { 2909 rare_data->unresolved_private_names.Clear(); 2910 } else { 2911 rare_data->unresolved_private_names.Rewind(tail); 2912 } 2913 rare_data->unresolved_private_names.Append(std::move(migrated_names)); 2914} 2915 2916Variable* ClassScope::LookupPrivateNameInScopeInfo(const AstRawString* name) { 2917 DCHECK(!scope_info_.is_null()); 2918 DCHECK_NULL(LookupLocalPrivateName(name)); 2919 DisallowGarbageCollection no_gc; 2920 2921 VariableLookupResult lookup_result; 2922 int index = scope_info_->ContextSlotIndex(name->string(), &lookup_result); 2923 if (index < 0) { 2924 return nullptr; 2925 } 2926 2927 DCHECK(IsConstVariableMode(lookup_result.mode)); 2928 DCHECK_EQ(lookup_result.init_flag, InitializationFlag::kNeedsInitialization); 2929 DCHECK_EQ(lookup_result.maybe_assigned_flag, MaybeAssignedFlag::kNotAssigned); 2930 2931 // Add the found private name to the map to speed up subsequent 2932 // lookups for the same name. 2933 bool was_added; 2934 Variable* var = DeclarePrivateName(name, lookup_result.mode, 2935 lookup_result.is_static_flag, &was_added); 2936 DCHECK(was_added); 2937 var->AllocateTo(VariableLocation::CONTEXT, index); 2938 return var; 2939} 2940 2941Variable* ClassScope::LookupPrivateName(VariableProxy* proxy) { 2942 DCHECK(!proxy->is_resolved()); 2943 2944 for (PrivateNameScopeIterator scope_iter(this); !scope_iter.Done(); 2945 scope_iter.Next()) { 2946 ClassScope* scope = scope_iter.GetScope(); 2947 // Try finding it in the private name map first, if it can't be found, 2948 // try the deseralized scope info. 2949 Variable* var = scope->LookupLocalPrivateName(proxy->raw_name()); 2950 if (var == nullptr && !scope->scope_info_.is_null()) { 2951 var = scope->LookupPrivateNameInScopeInfo(proxy->raw_name()); 2952 } 2953 if (var != nullptr) { 2954 return var; 2955 } 2956 } 2957 return nullptr; 2958} 2959 2960bool ClassScope::ResolvePrivateNames(ParseInfo* info) { 2961 RareData* rare_data = GetRareData(); 2962 if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) { 2963 return true; 2964 } 2965 2966 UnresolvedList& list = rare_data->unresolved_private_names; 2967 for (VariableProxy* proxy : list) { 2968 Variable* var = LookupPrivateName(proxy); 2969 if (var == nullptr) { 2970 // It's only possible to fail to resolve private names here if 2971 // this is at the top level or the private name is accessed through eval. 2972 DCHECK(info->flags().is_eval() || outer_scope_->is_script_scope()); 2973 Scanner::Location loc = proxy->location(); 2974 info->pending_error_handler()->ReportMessageAt( 2975 loc.beg_pos, loc.end_pos, 2976 MessageTemplate::kInvalidPrivateFieldResolution, proxy->raw_name()); 2977 return false; 2978 } else { 2979 proxy->BindTo(var); 2980 } 2981 } 2982 2983 // By now all unresolved private names should be resolved so 2984 // clear the list. 2985 list.Clear(); 2986 return true; 2987} 2988 2989VariableProxy* ClassScope::ResolvePrivateNamesPartially() { 2990 RareData* rare_data = GetRareData(); 2991 if (rare_data == nullptr || rare_data->unresolved_private_names.is_empty()) { 2992 return nullptr; 2993 } 2994 2995 PrivateNameScopeIterator private_name_scope_iter(this); 2996 private_name_scope_iter.Next(); 2997 UnresolvedList& unresolved = rare_data->unresolved_private_names; 2998 bool has_private_names = rare_data->private_name_map.capacity() > 0; 2999 3000 // If the class itself does not have private names, nor does it have 3001 // an outer private name scope, then we are certain any private name access 3002 // inside cannot be resolved. 3003 if (!has_private_names && private_name_scope_iter.Done() && 3004 !unresolved.is_empty()) { 3005 return unresolved.first(); 3006 } 3007 3008 for (VariableProxy* proxy = unresolved.first(); proxy != nullptr;) { 3009 DCHECK(proxy->IsPrivateName()); 3010 VariableProxy* next = proxy->next_unresolved(); 3011 unresolved.Remove(proxy); 3012 Variable* var = nullptr; 3013 3014 // If we can find private name in the current class scope, we can bind 3015 // them immediately because it's going to shadow any outer private names. 3016 if (has_private_names) { 3017 var = LookupLocalPrivateName(proxy->raw_name()); 3018 if (var != nullptr) { 3019 var->set_is_used(); 3020 proxy->BindTo(var); 3021 // If the variable being accessed is a static private method, we need to 3022 // save the class variable in the context to check that the receiver is 3023 // the class during runtime. 3024 has_explicit_static_private_methods_access_ |= 3025 (var->is_static() && 3026 IsPrivateMethodOrAccessorVariableMode(var->mode())); 3027 } 3028 } 3029 3030 // If the current scope does not have declared private names, 3031 // try looking from the outer class scope later. 3032 if (var == nullptr) { 3033 // There's no outer private name scope so we are certain that the variable 3034 // cannot be resolved later. 3035 if (private_name_scope_iter.Done()) { 3036 return proxy; 3037 } 3038 3039 // The private name may be found later in the outer private name scope, so 3040 // push it to the outer sopce. 3041 private_name_scope_iter.AddUnresolvedPrivateName(proxy); 3042 } 3043 3044 proxy = next; 3045 } 3046 3047 DCHECK(unresolved.is_empty()); 3048 return nullptr; 3049} 3050 3051Variable* ClassScope::DeclareBrandVariable(AstValueFactory* ast_value_factory, 3052 IsStaticFlag is_static_flag, 3053 int class_token_pos) { 3054 DCHECK_IMPLIES(GetRareData() != nullptr, GetRareData()->brand == nullptr); 3055 bool was_added; 3056 Variable* brand = Declare(zone(), ast_value_factory->dot_brand_string(), 3057 VariableMode::kConst, NORMAL_VARIABLE, 3058 InitializationFlag::kNeedsInitialization, 3059 MaybeAssignedFlag::kNotAssigned, &was_added); 3060 DCHECK(was_added); 3061 brand->set_is_static_flag(is_static_flag); 3062 brand->ForceContextAllocation(); 3063 brand->set_is_used(); 3064 EnsureRareData()->brand = brand; 3065 brand->set_initializer_position(class_token_pos); 3066 return brand; 3067} 3068 3069Variable* ClassScope::DeclareClassVariable(AstValueFactory* ast_value_factory, 3070 const AstRawString* name, 3071 int class_token_pos) { 3072 DCHECK_NULL(class_variable_); 3073 bool was_added; 3074 class_variable_ = 3075 Declare(zone(), name == nullptr ? ast_value_factory->dot_string() : name, 3076 VariableMode::kConst, NORMAL_VARIABLE, 3077 InitializationFlag::kNeedsInitialization, 3078 MaybeAssignedFlag::kMaybeAssigned, &was_added); 3079 DCHECK(was_added); 3080 class_variable_->set_initializer_position(class_token_pos); 3081 return class_variable_; 3082} 3083 3084PrivateNameScopeIterator::PrivateNameScopeIterator(Scope* start) 3085 : start_scope_(start), current_scope_(start) { 3086 if (!start->is_class_scope() || start->AsClassScope()->IsParsingHeritage()) { 3087 Next(); 3088 } 3089} 3090 3091void PrivateNameScopeIterator::Next() { 3092 DCHECK(!Done()); 3093 Scope* inner = current_scope_; 3094 Scope* scope = inner->outer_scope(); 3095 while (scope != nullptr) { 3096 if (scope->is_class_scope()) { 3097 if (!inner->private_name_lookup_skips_outer_class()) { 3098 current_scope_ = scope; 3099 return; 3100 } 3101 skipped_any_scopes_ = true; 3102 } 3103 inner = scope; 3104 scope = scope->outer_scope(); 3105 } 3106 current_scope_ = nullptr; 3107} 3108 3109void PrivateNameScopeIterator::AddUnresolvedPrivateName(VariableProxy* proxy) { 3110 // During a reparse, current_scope_->already_resolved_ may be true here, 3111 // because the class scope is deserialized while the function scope inside may 3112 // be new. 3113 DCHECK(!proxy->is_resolved()); 3114 DCHECK(proxy->IsPrivateName()); 3115 GetScope()->EnsureRareData()->unresolved_private_names.Add(proxy); 3116 // Any closure scope that contain uses of private names that skips over a 3117 // class scope due to heritage expressions need private name context chain 3118 // recalculation, since not all scopes require a Context or ScopeInfo. See 3119 // comment in DeclarationScope::RecalcPrivateNameContextChain. 3120 if (V8_UNLIKELY(skipped_any_scopes_)) { 3121 start_scope_->GetClosureScope()->RecordNeedsPrivateNameContextChainRecalc(); 3122 } 3123} 3124 3125} // namespace internal 3126} // namespace v8 3127