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 "src/accessors.h" 8 #include "src/ast/scopeinfo.h" 9 #include "src/bootstrapper.h" 10 #include "src/messages.h" 11 #include "src/parsing/parser.h" // for ParseInfo 12 13 namespace v8 { 14 namespace internal { 15 16 // ---------------------------------------------------------------------------- 17 // Implementation of LocalsMap 18 // 19 // Note: We are storing the handle locations as key values in the hash map. 20 // When inserting a new variable via Declare(), we rely on the fact that 21 // the handle location remains alive for the duration of that variable 22 // use. Because a Variable holding a handle with the same location exists 23 // this is ensured. 24 25 VariableMap::VariableMap(Zone* zone) 26 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), 27 zone_(zone) {} 28 VariableMap::~VariableMap() {} 29 30 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, 31 VariableMode mode, Variable::Kind kind, 32 InitializationFlag initialization_flag, 33 MaybeAssignedFlag maybe_assigned_flag) { 34 // AstRawStrings are unambiguous, i.e., the same string is always represented 35 // by the same AstRawString*. 36 // FIXME(marja): fix the type of Lookup. 37 Entry* p = 38 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 39 ZoneAllocationPolicy(zone())); 40 if (p->value == NULL) { 41 // The variable has not been declared yet -> insert it. 42 DCHECK(p->key == name); 43 p->value = new (zone()) Variable(scope, name, mode, kind, 44 initialization_flag, maybe_assigned_flag); 45 } 46 return reinterpret_cast<Variable*>(p->value); 47 } 48 49 50 Variable* VariableMap::Lookup(const AstRawString* name) { 51 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); 52 if (p != NULL) { 53 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); 54 DCHECK(p->value != NULL); 55 return reinterpret_cast<Variable*>(p->value); 56 } 57 return NULL; 58 } 59 60 61 SloppyBlockFunctionMap::SloppyBlockFunctionMap(Zone* zone) 62 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), 63 zone_(zone) {} 64 SloppyBlockFunctionMap::~SloppyBlockFunctionMap() {} 65 66 67 void SloppyBlockFunctionMap::Declare(const AstRawString* name, 68 SloppyBlockFunctionStatement* stmt) { 69 // AstRawStrings are unambiguous, i.e., the same string is always represented 70 // by the same AstRawString*. 71 Entry* p = 72 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), 73 ZoneAllocationPolicy(zone_)); 74 if (p->value == nullptr) { 75 p->value = new (zone_->New(sizeof(Vector))) Vector(zone_); 76 } 77 Vector* delegates = static_cast<Vector*>(p->value); 78 delegates->push_back(stmt); 79 } 80 81 82 // ---------------------------------------------------------------------------- 83 // Implementation of Scope 84 85 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, 86 AstValueFactory* ast_value_factory, FunctionKind function_kind) 87 : inner_scopes_(4, zone), 88 variables_(zone), 89 temps_(4, zone), 90 params_(4, zone), 91 unresolved_(16, zone), 92 decls_(4, zone), 93 module_descriptor_( 94 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), 95 sloppy_block_function_map_(zone), 96 already_resolved_(false), 97 ast_value_factory_(ast_value_factory), 98 zone_(zone) { 99 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), 100 function_kind); 101 // The outermost scope must be a script scope. 102 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); 103 } 104 105 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, 106 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) 107 : inner_scopes_(4, zone), 108 variables_(zone), 109 temps_(4, zone), 110 params_(4, zone), 111 unresolved_(16, zone), 112 decls_(4, zone), 113 module_descriptor_(NULL), 114 sloppy_block_function_map_(zone), 115 already_resolved_(true), 116 ast_value_factory_(value_factory), 117 zone_(zone) { 118 SetDefaults(scope_type, NULL, scope_info); 119 if (!scope_info.is_null()) { 120 num_heap_slots_ = scope_info_->ContextLength(); 121 } 122 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. 123 num_heap_slots_ = Max(num_heap_slots_, 124 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); 125 AddInnerScope(inner_scope); 126 } 127 128 Scope::Scope(Zone* zone, Scope* inner_scope, 129 const AstRawString* catch_variable_name, 130 AstValueFactory* value_factory) 131 : inner_scopes_(1, zone), 132 variables_(zone), 133 temps_(0, zone), 134 params_(0, zone), 135 unresolved_(0, zone), 136 decls_(0, zone), 137 module_descriptor_(NULL), 138 sloppy_block_function_map_(zone), 139 already_resolved_(true), 140 ast_value_factory_(value_factory), 141 zone_(zone) { 142 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); 143 AddInnerScope(inner_scope); 144 ++num_var_or_const_; 145 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 146 Variable* variable = variables_.Declare(this, 147 catch_variable_name, 148 VAR, 149 Variable::NORMAL, 150 kCreatedInitialized); 151 AllocateHeapSlot(variable); 152 } 153 154 155 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, 156 Handle<ScopeInfo> scope_info, 157 FunctionKind function_kind) { 158 outer_scope_ = outer_scope; 159 scope_type_ = scope_type; 160 is_declaration_scope_ = 161 is_eval_scope() || is_function_scope() || 162 is_module_scope() || is_script_scope(); 163 function_kind_ = function_kind; 164 scope_name_ = ast_value_factory_->empty_string(); 165 dynamics_ = nullptr; 166 receiver_ = nullptr; 167 new_target_ = nullptr; 168 function_ = nullptr; 169 arguments_ = nullptr; 170 this_function_ = nullptr; 171 scope_inside_with_ = false; 172 scope_calls_eval_ = false; 173 scope_uses_arguments_ = false; 174 scope_uses_super_property_ = false; 175 asm_module_ = false; 176 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; 177 // Inherit the language mode from the parent scope. 178 language_mode_ = 179 is_module_scope() 180 ? STRICT 181 : (outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY); 182 outer_scope_calls_sloppy_eval_ = false; 183 inner_scope_calls_eval_ = false; 184 scope_nonlinear_ = false; 185 force_eager_compilation_ = false; 186 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) 187 ? outer_scope->has_forced_context_allocation() : false; 188 num_var_or_const_ = 0; 189 num_stack_slots_ = 0; 190 num_heap_slots_ = 0; 191 num_global_slots_ = 0; 192 arity_ = 0; 193 has_simple_parameters_ = true; 194 rest_parameter_ = NULL; 195 rest_index_ = -1; 196 scope_info_ = scope_info; 197 start_position_ = RelocInfo::kNoPosition; 198 end_position_ = RelocInfo::kNoPosition; 199 is_hidden_ = false; 200 if (!scope_info.is_null()) { 201 scope_calls_eval_ = scope_info->CallsEval(); 202 language_mode_ = scope_info->language_mode(); 203 is_declaration_scope_ = scope_info->is_declaration_scope(); 204 function_kind_ = scope_info->function_kind(); 205 } 206 } 207 208 209 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, 210 Context* context, Scope* script_scope) { 211 // Reconstruct the outer scope chain from a closure's context chain. 212 Scope* current_scope = NULL; 213 Scope* innermost_scope = NULL; 214 while (!context->IsNativeContext()) { 215 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { 216 // For scope analysis, debug-evaluate is equivalent to a with scope. 217 Scope* with_scope = new (zone) 218 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), 219 script_scope->ast_value_factory_); 220 current_scope = with_scope; 221 // All the inner scopes are inside a with. 222 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { 223 s->scope_inside_with_ = true; 224 } 225 } else if (context->IsScriptContext()) { 226 ScopeInfo* scope_info = context->scope_info(); 227 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, 228 Handle<ScopeInfo>(scope_info), 229 script_scope->ast_value_factory_); 230 } else if (context->IsModuleContext()) { 231 ScopeInfo* scope_info = context->module()->scope_info(); 232 current_scope = new (zone) Scope(zone, current_scope, MODULE_SCOPE, 233 Handle<ScopeInfo>(scope_info), 234 script_scope->ast_value_factory_); 235 } else if (context->IsFunctionContext()) { 236 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); 237 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE, 238 Handle<ScopeInfo>(scope_info), 239 script_scope->ast_value_factory_); 240 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; 241 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; 242 } else if (context->IsBlockContext()) { 243 ScopeInfo* scope_info = context->scope_info(); 244 current_scope = new (zone) 245 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), 246 script_scope->ast_value_factory_); 247 } else { 248 DCHECK(context->IsCatchContext()); 249 String* name = context->catch_name(); 250 current_scope = new (zone) Scope( 251 zone, current_scope, 252 script_scope->ast_value_factory_->GetString(Handle<String>(name)), 253 script_scope->ast_value_factory_); 254 } 255 if (innermost_scope == NULL) innermost_scope = current_scope; 256 context = context->previous(); 257 } 258 259 script_scope->AddInnerScope(current_scope); 260 script_scope->PropagateScopeInfo(false); 261 return (innermost_scope == NULL) ? script_scope : innermost_scope; 262 } 263 264 265 bool Scope::Analyze(ParseInfo* info) { 266 DCHECK(info->literal() != NULL); 267 DCHECK(info->scope() == NULL); 268 Scope* scope = info->literal()->scope(); 269 Scope* top = scope; 270 271 // Traverse the scope tree up to the first unresolved scope or the global 272 // scope and start scope resolution and variable allocation from that scope. 273 while (!top->is_script_scope() && 274 !top->outer_scope()->already_resolved()) { 275 top = top->outer_scope(); 276 } 277 278 // Allocate the variables. 279 { 280 AstNodeFactory ast_node_factory(info->ast_value_factory()); 281 if (!top->AllocateVariables(info, &ast_node_factory)) { 282 DCHECK(top->pending_error_handler_.has_pending_error()); 283 top->pending_error_handler_.ThrowPendingError(info->isolate(), 284 info->script()); 285 return false; 286 } 287 } 288 289 #ifdef DEBUG 290 if (info->script_is_native() ? FLAG_print_builtin_scopes 291 : FLAG_print_scopes) { 292 scope->Print(); 293 } 294 scope->CheckScopePositions(); 295 #endif 296 297 info->set_scope(scope); 298 return true; 299 } 300 301 302 void Scope::Initialize() { 303 DCHECK(!already_resolved()); 304 305 // Add this scope as a new inner scope of the outer scope. 306 if (outer_scope_ != NULL) { 307 outer_scope_->inner_scopes_.Add(this, zone()); 308 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); 309 } else { 310 scope_inside_with_ = is_with_scope(); 311 } 312 313 // Declare convenience variables and the receiver. 314 if (is_declaration_scope() && has_this_declaration()) { 315 bool subclass_constructor = IsSubclassConstructor(function_kind_); 316 Variable* var = variables_.Declare( 317 this, ast_value_factory_->this_string(), 318 subclass_constructor ? CONST : VAR, Variable::THIS, 319 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); 320 receiver_ = var; 321 } 322 323 if (is_function_scope() && !is_arrow_scope()) { 324 // Declare 'arguments' variable which exists in all non arrow functions. 325 // Note that it might never be accessed, in which case it won't be 326 // allocated during variable allocation. 327 variables_.Declare(this, ast_value_factory_->arguments_string(), VAR, 328 Variable::ARGUMENTS, kCreatedInitialized); 329 330 variables_.Declare(this, ast_value_factory_->new_target_string(), CONST, 331 Variable::NORMAL, kCreatedInitialized); 332 333 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) || 334 IsAccessorFunction(function_kind_)) { 335 variables_.Declare(this, ast_value_factory_->this_function_string(), 336 CONST, Variable::NORMAL, kCreatedInitialized); 337 } 338 } 339 } 340 341 342 Scope* Scope::FinalizeBlockScope() { 343 DCHECK(is_block_scope()); 344 DCHECK(temps_.is_empty()); 345 DCHECK(params_.is_empty()); 346 347 if (num_var_or_const() > 0 || 348 (is_declaration_scope() && calls_sloppy_eval())) { 349 return this; 350 } 351 352 // Remove this scope from outer scope. 353 outer_scope()->RemoveInnerScope(this); 354 355 // Reparent inner scopes. 356 for (int i = 0; i < inner_scopes_.length(); i++) { 357 outer_scope()->AddInnerScope(inner_scopes_[i]); 358 } 359 360 // Move unresolved variables 361 for (int i = 0; i < unresolved_.length(); i++) { 362 outer_scope()->unresolved_.Add(unresolved_[i], zone()); 363 } 364 365 PropagateUsageFlagsToScope(outer_scope_); 366 367 return NULL; 368 } 369 370 371 void Scope::ReplaceOuterScope(Scope* outer) { 372 DCHECK_NOT_NULL(outer); 373 DCHECK_NOT_NULL(outer_scope_); 374 DCHECK(!already_resolved()); 375 DCHECK(!outer->already_resolved()); 376 DCHECK(!outer_scope_->already_resolved()); 377 outer_scope_->RemoveInnerScope(this); 378 outer->AddInnerScope(this); 379 outer_scope_ = outer; 380 } 381 382 383 void Scope::PropagateUsageFlagsToScope(Scope* other) { 384 DCHECK_NOT_NULL(other); 385 DCHECK(!already_resolved()); 386 DCHECK(!other->already_resolved()); 387 if (uses_arguments()) other->RecordArgumentsUsage(); 388 if (uses_super_property()) other->RecordSuperPropertyUsage(); 389 if (calls_eval()) other->RecordEvalCall(); 390 } 391 392 393 Variable* Scope::LookupLocal(const AstRawString* name) { 394 Variable* result = variables_.Lookup(name); 395 if (result != NULL || scope_info_.is_null()) { 396 return result; 397 } 398 Handle<String> name_handle = name->string(); 399 // The Scope is backed up by ScopeInfo. This means it cannot operate in a 400 // heap-independent mode, and all strings must be internalized immediately. So 401 // it's ok to get the Handle<String> here. 402 // If we have a serialized scope info, we might find the variable there. 403 // There should be no local slot with the given name. 404 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); 405 406 // Check context slot lookup. 407 VariableMode mode; 408 VariableLocation location = VariableLocation::CONTEXT; 409 InitializationFlag init_flag; 410 MaybeAssignedFlag maybe_assigned_flag; 411 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, 412 &init_flag, &maybe_assigned_flag); 413 if (index < 0) { 414 location = VariableLocation::GLOBAL; 415 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode, 416 &init_flag, &maybe_assigned_flag); 417 } 418 if (index < 0) { 419 // Check parameters. 420 index = scope_info_->ParameterIndex(*name_handle); 421 if (index < 0) return NULL; 422 423 mode = DYNAMIC; 424 location = VariableLocation::LOOKUP; 425 init_flag = kCreatedInitialized; 426 // Be conservative and flag parameters as maybe assigned. Better information 427 // would require ScopeInfo to serialize the maybe_assigned bit also for 428 // parameters. 429 maybe_assigned_flag = kMaybeAssigned; 430 } else { 431 DCHECK(location != VariableLocation::GLOBAL || 432 (is_script_scope() && IsDeclaredVariableMode(mode) && 433 !IsLexicalVariableMode(mode))); 434 } 435 436 Variable::Kind kind = Variable::NORMAL; 437 if (location == VariableLocation::CONTEXT && 438 index == scope_info_->ReceiverContextSlotIndex()) { 439 kind = Variable::THIS; 440 } 441 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and 442 // ARGUMENTS bindings as their corresponding Variable::Kind. 443 444 Variable* var = variables_.Declare(this, name, mode, kind, init_flag, 445 maybe_assigned_flag); 446 var->AllocateTo(location, index); 447 return var; 448 } 449 450 451 Variable* Scope::LookupFunctionVar(const AstRawString* name, 452 AstNodeFactory* factory) { 453 if (function_ != NULL && function_->proxy()->raw_name() == name) { 454 return function_->proxy()->var(); 455 } else if (!scope_info_.is_null()) { 456 // If we are backed by a scope info, try to lookup the variable there. 457 VariableMode mode; 458 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); 459 if (index < 0) return NULL; 460 Variable* var = new (zone()) 461 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); 462 VariableProxy* proxy = factory->NewVariableProxy(var); 463 VariableDeclaration* declaration = factory->NewVariableDeclaration( 464 proxy, mode, this, RelocInfo::kNoPosition); 465 DeclareFunctionVar(declaration); 466 var->AllocateTo(VariableLocation::CONTEXT, index); 467 return var; 468 } else { 469 return NULL; 470 } 471 } 472 473 474 Variable* Scope::Lookup(const AstRawString* name) { 475 for (Scope* scope = this; 476 scope != NULL; 477 scope = scope->outer_scope()) { 478 Variable* var = scope->LookupLocal(name); 479 if (var != NULL) return var; 480 } 481 return NULL; 482 } 483 484 485 Variable* Scope::DeclareParameter( 486 const AstRawString* name, VariableMode mode, 487 bool is_optional, bool is_rest, bool* is_duplicate) { 488 DCHECK(!already_resolved()); 489 DCHECK(is_function_scope()); 490 DCHECK(!is_optional || !is_rest); 491 Variable* var; 492 if (mode == TEMPORARY) { 493 var = NewTemporary(name); 494 } else { 495 var = variables_.Declare(this, name, mode, Variable::NORMAL, 496 kCreatedInitialized); 497 // TODO(wingo): Avoid O(n^2) check. 498 *is_duplicate = IsDeclaredParameter(name); 499 } 500 if (!is_optional && !is_rest && arity_ == params_.length()) { 501 ++arity_; 502 } 503 if (is_rest) { 504 DCHECK_NULL(rest_parameter_); 505 rest_parameter_ = var; 506 rest_index_ = num_parameters(); 507 } 508 params_.Add(var, zone()); 509 return var; 510 } 511 512 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, 513 InitializationFlag init_flag, Variable::Kind kind, 514 MaybeAssignedFlag maybe_assigned_flag) { 515 DCHECK(!already_resolved()); 516 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are 517 // introduced during variable allocation, and TEMPORARY variables are 518 // allocated via NewTemporary(). 519 DCHECK(IsDeclaredVariableMode(mode)); 520 ++num_var_or_const_; 521 return variables_.Declare(this, name, mode, kind, init_flag, 522 maybe_assigned_flag); 523 } 524 525 526 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { 527 DCHECK(is_script_scope()); 528 return variables_.Declare(this, 529 name, 530 DYNAMIC_GLOBAL, 531 Variable::NORMAL, 532 kCreatedInitialized); 533 } 534 535 536 bool Scope::RemoveUnresolved(VariableProxy* var) { 537 // Most likely (always?) any variable we want to remove 538 // was just added before, so we search backwards. 539 for (int i = unresolved_.length(); i-- > 0;) { 540 if (unresolved_[i] == var) { 541 unresolved_.Remove(i); 542 return true; 543 } 544 } 545 return false; 546 } 547 548 549 Variable* Scope::NewTemporary(const AstRawString* name) { 550 DCHECK(!already_resolved()); 551 Scope* scope = this->ClosureScope(); 552 Variable* var = new(zone()) Variable(scope, 553 name, 554 TEMPORARY, 555 Variable::NORMAL, 556 kCreatedInitialized); 557 scope->AddTemporary(var); 558 return var; 559 } 560 561 int Scope::RemoveTemporary(Variable* var) { 562 DCHECK_NOT_NULL(var); 563 // Temporaries are only placed in ClosureScopes. 564 DCHECK_EQ(ClosureScope(), this); 565 DCHECK_EQ(var->scope()->ClosureScope(), var->scope()); 566 // If the temporary is not here, return quickly. 567 if (var->scope() != this) return -1; 568 // Most likely (always?) any temporary variable we want to remove 569 // was just added before, so we search backwards. 570 for (int i = temps_.length(); i-- > 0;) { 571 if (temps_[i] == var) { 572 // Don't shrink temps_, as callers of this method expect 573 // the returned indices to be unique per-scope. 574 temps_[i] = nullptr; 575 return i; 576 } 577 } 578 return -1; 579 } 580 581 582 void Scope::AddDeclaration(Declaration* declaration) { 583 decls_.Add(declaration, zone()); 584 } 585 586 587 Declaration* Scope::CheckConflictingVarDeclarations() { 588 int length = decls_.length(); 589 for (int i = 0; i < length; i++) { 590 Declaration* decl = decls_[i]; 591 // We don't create a separate scope to hold the function name of a function 592 // expression, so we have to make sure not to consider it when checking for 593 // conflicts (since it's conceptually "outside" the declaration scope). 594 if (is_function_scope() && decl == function()) continue; 595 if (IsLexicalVariableMode(decl->mode()) && !is_block_scope()) continue; 596 const AstRawString* name = decl->proxy()->raw_name(); 597 598 // Iterate through all scopes until and including the declaration scope. 599 Scope* previous = NULL; 600 Scope* current = decl->scope(); 601 // Lexical vs lexical conflicts within the same scope have already been 602 // captured in Parser::Declare. The only conflicts we still need to check 603 // are lexical vs VAR, or any declarations within a declaration block scope 604 // vs lexical declarations in its surrounding (function) scope. 605 if (IsLexicalVariableMode(decl->mode())) current = current->outer_scope_; 606 do { 607 // There is a conflict if there exists a non-VAR binding. 608 Variable* other_var = current->variables_.Lookup(name); 609 if (other_var != NULL && IsLexicalVariableMode(other_var->mode())) { 610 return decl; 611 } 612 previous = current; 613 current = current->outer_scope_; 614 } while (!previous->is_declaration_scope()); 615 } 616 return NULL; 617 } 618 619 620 class VarAndOrder { 621 public: 622 VarAndOrder(Variable* var, int order) : var_(var), order_(order) { } 623 Variable* var() const { return var_; } 624 int order() const { return order_; } 625 static int Compare(const VarAndOrder* a, const VarAndOrder* b) { 626 return a->order_ - b->order_; 627 } 628 629 private: 630 Variable* var_; 631 int order_; 632 }; 633 634 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, 635 ZoneList<Variable*>* context_locals, 636 ZoneList<Variable*>* context_globals) { 637 DCHECK(stack_locals != NULL); 638 DCHECK(context_locals != NULL); 639 DCHECK(context_globals != NULL); 640 641 // Collect temporaries which are always allocated on the stack, unless the 642 // context as a whole has forced context allocation. 643 for (int i = 0; i < temps_.length(); i++) { 644 Variable* var = temps_[i]; 645 if (var == nullptr) continue; 646 if (var->is_used()) { 647 if (var->IsContextSlot()) { 648 DCHECK(has_forced_context_allocation()); 649 context_locals->Add(var, zone()); 650 } else if (var->IsStackLocal()) { 651 stack_locals->Add(var, zone()); 652 } else { 653 DCHECK(var->IsParameter()); 654 } 655 } 656 } 657 658 // Collect declared local variables. 659 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); 660 for (VariableMap::Entry* p = variables_.Start(); 661 p != NULL; 662 p = variables_.Next(p)) { 663 Variable* var = reinterpret_cast<Variable*>(p->value); 664 if (var->is_used()) { 665 vars.Add(VarAndOrder(var, p->order), zone()); 666 } 667 } 668 vars.Sort(VarAndOrder::Compare); 669 int var_count = vars.length(); 670 for (int i = 0; i < var_count; i++) { 671 Variable* var = vars[i].var(); 672 if (var->IsStackLocal()) { 673 stack_locals->Add(var, zone()); 674 } else if (var->IsContextSlot()) { 675 context_locals->Add(var, zone()); 676 } else if (var->IsGlobalSlot()) { 677 context_globals->Add(var, zone()); 678 } 679 } 680 } 681 682 683 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) { 684 // 1) Propagate scope information. 685 bool outer_scope_calls_sloppy_eval = false; 686 if (outer_scope_ != NULL) { 687 outer_scope_calls_sloppy_eval = 688 outer_scope_->outer_scope_calls_sloppy_eval() | 689 outer_scope_->calls_sloppy_eval(); 690 } 691 PropagateScopeInfo(outer_scope_calls_sloppy_eval); 692 693 // 2) Resolve variables. 694 if (!ResolveVariablesRecursively(info, factory)) return false; 695 696 // 3) Allocate variables. 697 AllocateVariablesRecursively(info->isolate()); 698 699 return true; 700 } 701 702 703 bool Scope::HasTrivialContext() const { 704 // A function scope has a trivial context if it always is the global 705 // context. We iteratively scan out the context chain to see if 706 // there is anything that makes this scope non-trivial; otherwise we 707 // return true. 708 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { 709 if (scope->is_eval_scope()) return false; 710 if (scope->scope_inside_with_) return false; 711 if (scope->ContextLocalCount() > 0) return false; 712 if (scope->ContextGlobalCount() > 0) return false; 713 } 714 return true; 715 } 716 717 718 bool Scope::HasTrivialOuterContext() const { 719 Scope* outer = outer_scope_; 720 if (outer == NULL) return true; 721 // Note that the outer context may be trivial in general, but the current 722 // scope may be inside a 'with' statement in which case the outer context 723 // for this scope is not trivial. 724 return !scope_inside_with_ && outer->HasTrivialContext(); 725 } 726 727 728 bool Scope::AllowsLazyParsing() const { 729 // If we are inside a block scope, we must parse eagerly to find out how 730 // to allocate variables on the block scope. At this point, declarations may 731 // not have yet been parsed. 732 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { 733 if (scope->is_block_scope()) return false; 734 } 735 return AllowsLazyCompilation(); 736 } 737 738 739 bool Scope::AllowsLazyCompilation() const { return !force_eager_compilation_; } 740 741 742 bool Scope::AllowsLazyCompilationWithoutContext() const { 743 return !force_eager_compilation_ && HasTrivialOuterContext(); 744 } 745 746 747 int Scope::ContextChainLength(Scope* scope) { 748 int n = 0; 749 for (Scope* s = this; s != scope; s = s->outer_scope_) { 750 DCHECK(s != NULL); // scope must be in the scope chain 751 if (s->NeedsContext()) n++; 752 } 753 return n; 754 } 755 756 757 int Scope::MaxNestedContextChainLength() { 758 int max_context_chain_length = 0; 759 for (int i = 0; i < inner_scopes_.length(); i++) { 760 Scope* scope = inner_scopes_[i]; 761 max_context_chain_length = std::max(scope->MaxNestedContextChainLength(), 762 max_context_chain_length); 763 } 764 if (NeedsContext()) { 765 max_context_chain_length += 1; 766 } 767 return max_context_chain_length; 768 } 769 770 771 Scope* Scope::DeclarationScope() { 772 Scope* scope = this; 773 while (!scope->is_declaration_scope()) { 774 scope = scope->outer_scope(); 775 } 776 return scope; 777 } 778 779 780 Scope* Scope::ClosureScope() { 781 Scope* scope = this; 782 while (!scope->is_declaration_scope() || scope->is_block_scope()) { 783 scope = scope->outer_scope(); 784 } 785 return scope; 786 } 787 788 789 Scope* Scope::ReceiverScope() { 790 Scope* scope = this; 791 while (!scope->is_script_scope() && 792 (!scope->is_function_scope() || scope->is_arrow_scope())) { 793 scope = scope->outer_scope(); 794 } 795 return scope; 796 } 797 798 799 800 Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) { 801 if (scope_info_.is_null()) { 802 scope_info_ = ScopeInfo::Create(isolate, zone(), this); 803 } 804 return scope_info_; 805 } 806 807 Handle<StringSet> Scope::CollectNonLocals(Handle<StringSet> non_locals) { 808 // Collect non-local variables referenced in the scope. 809 // TODO(yangguo): store non-local variables explicitly if we can no longer 810 // rely on unresolved_ to find them. 811 for (int i = 0; i < unresolved_.length(); i++) { 812 VariableProxy* proxy = unresolved_[i]; 813 if (proxy->is_resolved() && proxy->var()->IsStackAllocated()) continue; 814 Handle<String> name = proxy->name(); 815 non_locals = StringSet::Add(non_locals, name); 816 } 817 for (int i = 0; i < inner_scopes_.length(); i++) { 818 non_locals = inner_scopes_[i]->CollectNonLocals(non_locals); 819 } 820 return non_locals; 821 } 822 823 824 #ifdef DEBUG 825 static const char* Header(ScopeType scope_type, FunctionKind function_kind, 826 bool is_declaration_scope) { 827 switch (scope_type) { 828 case EVAL_SCOPE: return "eval"; 829 // TODO(adamk): Should we print concise method scopes specially? 830 case FUNCTION_SCOPE: 831 if (IsGeneratorFunction(function_kind)) return "function*"; 832 if (IsAsyncFunction(function_kind)) return "async function"; 833 if (IsArrowFunction(function_kind)) return "arrow"; 834 return "function"; 835 case MODULE_SCOPE: return "module"; 836 case SCRIPT_SCOPE: return "global"; 837 case CATCH_SCOPE: return "catch"; 838 case BLOCK_SCOPE: return is_declaration_scope ? "varblock" : "block"; 839 case WITH_SCOPE: return "with"; 840 } 841 UNREACHABLE(); 842 return NULL; 843 } 844 845 846 static void Indent(int n, const char* str) { 847 PrintF("%*s%s", n, "", str); 848 } 849 850 851 static void PrintName(const AstRawString* name) { 852 PrintF("%.*s", name->length(), name->raw_data()); 853 } 854 855 856 static void PrintLocation(Variable* var) { 857 switch (var->location()) { 858 case VariableLocation::UNALLOCATED: 859 break; 860 case VariableLocation::PARAMETER: 861 PrintF("parameter[%d]", var->index()); 862 break; 863 case VariableLocation::LOCAL: 864 PrintF("local[%d]", var->index()); 865 break; 866 case VariableLocation::CONTEXT: 867 PrintF("context[%d]", var->index()); 868 break; 869 case VariableLocation::GLOBAL: 870 PrintF("global[%d]", var->index()); 871 break; 872 case VariableLocation::LOOKUP: 873 PrintF("lookup"); 874 break; 875 } 876 } 877 878 879 static void PrintVar(int indent, Variable* var) { 880 if (var->is_used() || !var->IsUnallocated()) { 881 Indent(indent, Variable::Mode2String(var->mode())); 882 PrintF(" "); 883 if (var->raw_name()->IsEmpty()) 884 PrintF(".%p", reinterpret_cast<void*>(var)); 885 else 886 PrintName(var->raw_name()); 887 PrintF("; // "); 888 PrintLocation(var); 889 bool comma = !var->IsUnallocated(); 890 if (var->has_forced_context_allocation()) { 891 if (comma) PrintF(", "); 892 PrintF("forced context allocation"); 893 comma = true; 894 } 895 if (var->maybe_assigned() == kMaybeAssigned) { 896 if (comma) PrintF(", "); 897 PrintF("maybe assigned"); 898 } 899 PrintF("\n"); 900 } 901 } 902 903 904 static void PrintMap(int indent, VariableMap* map) { 905 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { 906 Variable* var = reinterpret_cast<Variable*>(p->value); 907 if (var == NULL) { 908 Indent(indent, "<?>\n"); 909 } else { 910 PrintVar(indent, var); 911 } 912 } 913 } 914 915 916 void Scope::Print(int n) { 917 int n0 = (n > 0 ? n : 0); 918 int n1 = n0 + 2; // indentation 919 920 // Print header. 921 Indent(n0, Header(scope_type_, function_kind_, is_declaration_scope())); 922 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) { 923 PrintF(" "); 924 PrintName(scope_name_); 925 } 926 927 // Print parameters, if any. 928 if (is_function_scope()) { 929 PrintF(" ("); 930 for (int i = 0; i < params_.length(); i++) { 931 if (i > 0) PrintF(", "); 932 const AstRawString* name = params_[i]->raw_name(); 933 if (name->IsEmpty()) 934 PrintF(".%p", reinterpret_cast<void*>(params_[i])); 935 else 936 PrintName(name); 937 } 938 PrintF(")"); 939 } 940 941 PrintF(" { // (%d, %d)\n", start_position(), end_position()); 942 943 // Function name, if any (named function literals, only). 944 if (function_ != NULL) { 945 Indent(n1, "// (local) function name: "); 946 PrintName(function_->proxy()->raw_name()); 947 PrintF("\n"); 948 } 949 950 // Scope info. 951 if (HasTrivialOuterContext()) { 952 Indent(n1, "// scope has trivial outer context\n"); 953 } 954 if (is_strict(language_mode())) { 955 Indent(n1, "// strict mode scope\n"); 956 } 957 if (asm_module_) Indent(n1, "// scope is an asm module\n"); 958 if (asm_function_) Indent(n1, "// scope is an asm function\n"); 959 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 960 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 961 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); 962 if (scope_uses_super_property_) 963 Indent(n1, "// scope uses 'super' property\n"); 964 if (outer_scope_calls_sloppy_eval_) { 965 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); 966 } 967 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 968 if (num_stack_slots_ > 0) { 969 Indent(n1, "// "); 970 PrintF("%d stack slots\n", num_stack_slots_); 971 } 972 if (num_heap_slots_ > 0) { 973 Indent(n1, "// "); 974 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, 975 num_global_slots_); 976 } 977 978 // Print locals. 979 if (function_ != NULL) { 980 Indent(n1, "// function var:\n"); 981 PrintVar(n1, function_->proxy()->var()); 982 } 983 984 if (temps_.length() > 0) { 985 bool printed_header = false; 986 for (int i = 0; i < temps_.length(); i++) { 987 if (temps_[i] != nullptr) { 988 if (!printed_header) { 989 printed_header = true; 990 Indent(n1, "// temporary vars:\n"); 991 } 992 PrintVar(n1, temps_[i]); 993 } 994 } 995 } 996 997 if (variables_.Start() != NULL) { 998 Indent(n1, "// local vars:\n"); 999 PrintMap(n1, &variables_); 1000 } 1001 1002 if (dynamics_ != NULL) { 1003 Indent(n1, "// dynamic vars:\n"); 1004 PrintMap(n1, dynamics_->GetMap(DYNAMIC)); 1005 PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL)); 1006 PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL)); 1007 } 1008 1009 // Print inner scopes (disable by providing negative n). 1010 if (n >= 0) { 1011 for (int i = 0; i < inner_scopes_.length(); i++) { 1012 PrintF("\n"); 1013 inner_scopes_[i]->Print(n1); 1014 } 1015 } 1016 1017 Indent(n0, "}\n"); 1018 } 1019 1020 void Scope::CheckScopePositions() { 1021 // A scope is allowed to have invalid positions if it is hidden and has no 1022 // inner scopes 1023 if (!is_hidden() && inner_scopes_.length() == 0) { 1024 CHECK_NE(RelocInfo::kNoPosition, start_position()); 1025 CHECK_NE(RelocInfo::kNoPosition, end_position()); 1026 } 1027 for (Scope* scope : inner_scopes_) scope->CheckScopePositions(); 1028 } 1029 #endif // DEBUG 1030 1031 1032 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { 1033 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); 1034 VariableMap* map = dynamics_->GetMap(mode); 1035 Variable* var = map->Lookup(name); 1036 if (var == NULL) { 1037 // Declare a new non-local. 1038 InitializationFlag init_flag = (mode == VAR) 1039 ? kCreatedInitialized : kNeedsInitialization; 1040 var = map->Declare(NULL, 1041 name, 1042 mode, 1043 Variable::NORMAL, 1044 init_flag); 1045 // Allocate it by giving it a dynamic lookup. 1046 var->AllocateTo(VariableLocation::LOOKUP, -1); 1047 } 1048 return var; 1049 } 1050 1051 1052 Variable* Scope::LookupRecursive(VariableProxy* proxy, 1053 BindingKind* binding_kind, 1054 AstNodeFactory* factory) { 1055 DCHECK(binding_kind != NULL); 1056 if (already_resolved() && is_with_scope()) { 1057 // Short-cut: if the scope is deserialized from a scope info, variable 1058 // allocation is already fixed. We can simply return with dynamic lookup. 1059 *binding_kind = DYNAMIC_LOOKUP; 1060 return NULL; 1061 } 1062 1063 // Try to find the variable in this scope. 1064 Variable* var = LookupLocal(proxy->raw_name()); 1065 1066 // We found a variable and we are done. (Even if there is an 'eval' in 1067 // this scope which introduces the same variable again, the resulting 1068 // variable remains the same.) 1069 if (var != NULL) { 1070 *binding_kind = BOUND; 1071 return var; 1072 } 1073 1074 // We did not find a variable locally. Check against the function variable, 1075 // if any. We can do this for all scopes, since the function variable is 1076 // only present - if at all - for function scopes. 1077 *binding_kind = UNBOUND; 1078 var = LookupFunctionVar(proxy->raw_name(), factory); 1079 if (var != NULL) { 1080 *binding_kind = BOUND; 1081 } else if (outer_scope_ != NULL) { 1082 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); 1083 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { 1084 var->ForceContextAllocation(); 1085 } 1086 } else { 1087 DCHECK(is_script_scope()); 1088 } 1089 1090 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. 1091 // TODO(wingo): There are other variables in this category; add them. 1092 bool name_can_be_shadowed = var == nullptr || !var->is_this(); 1093 1094 if (is_with_scope() && name_can_be_shadowed) { 1095 DCHECK(!already_resolved()); 1096 // The current scope is a with scope, so the variable binding can not be 1097 // statically resolved. However, note that it was necessary to do a lookup 1098 // in the outer scope anyway, because if a binding exists in an outer scope, 1099 // the associated variable has to be marked as potentially being accessed 1100 // from inside of an inner with scope (the property may not be in the 'with' 1101 // object). 1102 if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned(); 1103 *binding_kind = DYNAMIC_LOOKUP; 1104 return NULL; 1105 } else if (calls_sloppy_eval() && is_declaration_scope() && 1106 !is_script_scope() && name_can_be_shadowed) { 1107 // A variable binding may have been found in an outer scope, but the current 1108 // scope makes a sloppy 'eval' call, so the found variable may not be 1109 // the correct one (the 'eval' may introduce a binding with the same name). 1110 // In that case, change the lookup result to reflect this situation. 1111 // Only scopes that can host var bindings (declaration scopes) need be 1112 // considered here (this excludes block and catch scopes), and variable 1113 // lookups at script scope are always dynamic. 1114 if (*binding_kind == BOUND) { 1115 *binding_kind = BOUND_EVAL_SHADOWED; 1116 } else if (*binding_kind == UNBOUND) { 1117 *binding_kind = UNBOUND_EVAL_SHADOWED; 1118 } 1119 } 1120 return var; 1121 } 1122 1123 1124 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, 1125 AstNodeFactory* factory) { 1126 DCHECK(info->script_scope()->is_script_scope()); 1127 1128 // If the proxy is already resolved there's nothing to do 1129 // (functions and consts may be resolved by the parser). 1130 if (proxy->is_resolved()) return true; 1131 1132 // Otherwise, try to resolve the variable. 1133 BindingKind binding_kind; 1134 Variable* var = LookupRecursive(proxy, &binding_kind, factory); 1135 1136 #ifdef DEBUG 1137 if (info->script_is_native()) { 1138 // To avoid polluting the global object in native scripts 1139 // - Variables must not be allocated to the global scope. 1140 CHECK_NOT_NULL(outer_scope()); 1141 // - Variables must be bound locally or unallocated. 1142 if (BOUND != binding_kind) { 1143 // The following variable name may be minified. If so, disable 1144 // minification in js2c.py for better output. 1145 Handle<String> name = proxy->raw_name()->string(); 1146 V8_Fatal(__FILE__, __LINE__, "Unbound variable: '%s' in native script.", 1147 name->ToCString().get()); 1148 } 1149 VariableLocation location = var->location(); 1150 CHECK(location == VariableLocation::LOCAL || 1151 location == VariableLocation::CONTEXT || 1152 location == VariableLocation::PARAMETER || 1153 location == VariableLocation::UNALLOCATED); 1154 } 1155 #endif 1156 1157 switch (binding_kind) { 1158 case BOUND: 1159 break; 1160 1161 case BOUND_EVAL_SHADOWED: 1162 // We either found a variable binding that might be shadowed by eval or 1163 // gave up on it (e.g. by encountering a local with the same in the outer 1164 // scope which was not promoted to a context, this can happen if we use 1165 // debugger to evaluate arbitrary expressions at a break point). 1166 if (var->IsGlobalObjectProperty()) { 1167 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); 1168 } else if (var->is_dynamic()) { 1169 var = NonLocal(proxy->raw_name(), DYNAMIC); 1170 } else { 1171 Variable* invalidated = var; 1172 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); 1173 var->set_local_if_not_shadowed(invalidated); 1174 } 1175 break; 1176 1177 case UNBOUND: 1178 // No binding has been found. Declare a variable on the global object. 1179 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name()); 1180 break; 1181 1182 case UNBOUND_EVAL_SHADOWED: 1183 // No binding has been found. But some scope makes a sloppy 'eval' call. 1184 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); 1185 break; 1186 1187 case DYNAMIC_LOOKUP: 1188 // The variable could not be resolved statically. 1189 var = NonLocal(proxy->raw_name(), DYNAMIC); 1190 break; 1191 } 1192 1193 DCHECK(var != NULL); 1194 if (proxy->is_assigned()) var->set_maybe_assigned(); 1195 1196 proxy->BindTo(var); 1197 1198 return true; 1199 } 1200 1201 1202 bool Scope::ResolveVariablesRecursively(ParseInfo* info, 1203 AstNodeFactory* factory) { 1204 DCHECK(info->script_scope()->is_script_scope()); 1205 1206 // Resolve unresolved variables for this scope. 1207 for (int i = 0; i < unresolved_.length(); i++) { 1208 if (!ResolveVariable(info, unresolved_[i], factory)) return false; 1209 } 1210 1211 // Resolve unresolved variables for inner scopes. 1212 for (int i = 0; i < inner_scopes_.length(); i++) { 1213 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) 1214 return false; 1215 } 1216 1217 return true; 1218 } 1219 1220 1221 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { 1222 if (outer_scope_calls_sloppy_eval) { 1223 outer_scope_calls_sloppy_eval_ = true; 1224 } 1225 1226 bool calls_sloppy_eval = 1227 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; 1228 for (int i = 0; i < inner_scopes_.length(); i++) { 1229 Scope* inner = inner_scopes_[i]; 1230 inner->PropagateScopeInfo(calls_sloppy_eval); 1231 if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) { 1232 inner_scope_calls_eval_ = true; 1233 } 1234 if (inner->force_eager_compilation_) { 1235 force_eager_compilation_ = true; 1236 } 1237 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { 1238 inner->asm_function_ = true; 1239 } 1240 } 1241 } 1242 1243 1244 bool Scope::MustAllocate(Variable* var) { 1245 // Give var a read/write use if there is a chance it might be accessed 1246 // via an eval() call. This is only possible if the variable has a 1247 // visible name. 1248 if ((var->is_this() || !var->raw_name()->IsEmpty()) && 1249 (var->has_forced_context_allocation() || scope_calls_eval_ || 1250 inner_scope_calls_eval_ || is_catch_scope() || is_block_scope() || 1251 is_module_scope() || is_script_scope())) { 1252 var->set_is_used(); 1253 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); 1254 } 1255 // Global variables do not need to be allocated. 1256 return !var->IsGlobalObjectProperty() && var->is_used(); 1257 } 1258 1259 1260 bool Scope::MustAllocateInContext(Variable* var) { 1261 // If var is accessed from an inner scope, or if there is a possibility 1262 // that it might be accessed from the current or an inner scope (through 1263 // an eval() call or a runtime with lookup), it must be allocated in the 1264 // context. 1265 // 1266 // Exceptions: If the scope as a whole has forced context allocation, all 1267 // variables will have context allocation, even temporaries. Otherwise 1268 // temporary variables are always stack-allocated. Catch-bound variables are 1269 // always context-allocated. 1270 if (has_forced_context_allocation()) return true; 1271 if (var->mode() == TEMPORARY) return false; 1272 if (is_catch_scope() || is_module_scope()) return true; 1273 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; 1274 return var->has_forced_context_allocation() || scope_calls_eval_ || 1275 inner_scope_calls_eval_; 1276 } 1277 1278 1279 bool Scope::HasArgumentsParameter(Isolate* isolate) { 1280 for (int i = 0; i < params_.length(); i++) { 1281 if (params_[i]->name().is_identical_to( 1282 isolate->factory()->arguments_string())) { 1283 return true; 1284 } 1285 } 1286 return false; 1287 } 1288 1289 1290 void Scope::AllocateStackSlot(Variable* var) { 1291 if (is_block_scope()) { 1292 outer_scope()->DeclarationScope()->AllocateStackSlot(var); 1293 } else { 1294 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); 1295 } 1296 } 1297 1298 1299 void Scope::AllocateHeapSlot(Variable* var) { 1300 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++); 1301 } 1302 1303 1304 void Scope::AllocateParameterLocals(Isolate* isolate) { 1305 DCHECK(is_function_scope()); 1306 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); 1307 // Functions have 'arguments' declared implicitly in all non arrow functions. 1308 DCHECK(arguments != nullptr || is_arrow_scope()); 1309 1310 bool uses_sloppy_arguments = false; 1311 1312 if (arguments != nullptr && MustAllocate(arguments) && 1313 !HasArgumentsParameter(isolate)) { 1314 // 'arguments' is used. Unless there is also a parameter called 1315 // 'arguments', we must be conservative and allocate all parameters to 1316 // the context assuming they will be captured by the arguments object. 1317 // If we have a parameter named 'arguments', a (new) value is always 1318 // assigned to it via the function invocation. Then 'arguments' denotes 1319 // that specific parameter value and cannot be used to access the 1320 // parameters, which is why we don't need to allocate an arguments 1321 // object in that case. 1322 1323 // We are using 'arguments'. Tell the code generator that is needs to 1324 // allocate the arguments object by setting 'arguments_'. 1325 arguments_ = arguments; 1326 1327 // In strict mode 'arguments' does not alias formal parameters. 1328 // Therefore in strict mode we allocate parameters as if 'arguments' 1329 // were not used. 1330 // If the parameter list is not simple, arguments isn't sloppy either. 1331 uses_sloppy_arguments = 1332 is_sloppy(language_mode()) && has_simple_parameters(); 1333 } 1334 1335 if (rest_parameter_ && !MustAllocate(rest_parameter_)) { 1336 rest_parameter_ = NULL; 1337 } 1338 1339 // The same parameter may occur multiple times in the parameters_ list. 1340 // If it does, and if it is not copied into the context object, it must 1341 // receive the highest parameter index for that parameter; thus iteration 1342 // order is relevant! 1343 for (int i = params_.length() - 1; i >= 0; --i) { 1344 Variable* var = params_[i]; 1345 if (var == rest_parameter_) continue; 1346 1347 DCHECK(var->scope() == this); 1348 if (uses_sloppy_arguments || has_forced_context_allocation()) { 1349 // Force context allocation of the parameter. 1350 var->ForceContextAllocation(); 1351 } 1352 AllocateParameter(var, i); 1353 } 1354 } 1355 1356 1357 void Scope::AllocateParameter(Variable* var, int index) { 1358 if (MustAllocate(var)) { 1359 if (MustAllocateInContext(var)) { 1360 DCHECK(var->IsUnallocated() || var->IsContextSlot()); 1361 if (var->IsUnallocated()) { 1362 AllocateHeapSlot(var); 1363 } 1364 } else { 1365 DCHECK(var->IsUnallocated() || var->IsParameter()); 1366 if (var->IsUnallocated()) { 1367 var->AllocateTo(VariableLocation::PARAMETER, index); 1368 } 1369 } 1370 } else { 1371 DCHECK(!var->IsGlobalSlot()); 1372 } 1373 } 1374 1375 1376 void Scope::AllocateReceiver() { 1377 DCHECK_NOT_NULL(receiver()); 1378 DCHECK_EQ(receiver()->scope(), this); 1379 1380 if (has_forced_context_allocation()) { 1381 // Force context allocation of the receiver. 1382 receiver()->ForceContextAllocation(); 1383 } 1384 AllocateParameter(receiver(), -1); 1385 } 1386 1387 1388 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) { 1389 DCHECK(var->scope() == this); 1390 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || 1391 !var->IsStackLocal()); 1392 if (var->IsUnallocated() && MustAllocate(var)) { 1393 if (MustAllocateInContext(var)) { 1394 AllocateHeapSlot(var); 1395 } else { 1396 AllocateStackSlot(var); 1397 } 1398 } 1399 } 1400 1401 1402 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) { 1403 DCHECK(var->scope() == this); 1404 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || 1405 !var->IsStackLocal()); 1406 if (var->IsUnallocated()) { 1407 if (var->IsStaticGlobalObjectProperty()) { 1408 DCHECK_EQ(-1, var->index()); 1409 DCHECK(var->name()->IsString()); 1410 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_++); 1411 num_global_slots_++; 1412 } else { 1413 // There must be only DYNAMIC_GLOBAL in the script scope. 1414 DCHECK(!is_script_scope() || DYNAMIC_GLOBAL == var->mode()); 1415 } 1416 } 1417 } 1418 1419 1420 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) { 1421 // All variables that have no rewrite yet are non-parameter locals. 1422 for (int i = 0; i < temps_.length(); i++) { 1423 if (temps_[i] == nullptr) continue; 1424 AllocateNonParameterLocal(isolate, temps_[i]); 1425 } 1426 1427 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); 1428 for (VariableMap::Entry* p = variables_.Start(); 1429 p != NULL; 1430 p = variables_.Next(p)) { 1431 Variable* var = reinterpret_cast<Variable*>(p->value); 1432 vars.Add(VarAndOrder(var, p->order), zone()); 1433 } 1434 vars.Sort(VarAndOrder::Compare); 1435 int var_count = vars.length(); 1436 for (int i = 0; i < var_count; i++) { 1437 AllocateNonParameterLocal(isolate, vars[i].var()); 1438 } 1439 1440 if (FLAG_global_var_shortcuts) { 1441 for (int i = 0; i < var_count; i++) { 1442 AllocateDeclaredGlobal(isolate, vars[i].var()); 1443 } 1444 } 1445 1446 // For now, function_ must be allocated at the very end. If it gets 1447 // allocated in the context, it must be the last slot in the context, 1448 // because of the current ScopeInfo implementation (see 1449 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 1450 if (function_ != nullptr) { 1451 AllocateNonParameterLocal(isolate, function_->proxy()->var()); 1452 } 1453 1454 if (rest_parameter_ != nullptr) { 1455 AllocateNonParameterLocal(isolate, rest_parameter_); 1456 } 1457 1458 Variable* new_target_var = 1459 LookupLocal(ast_value_factory_->new_target_string()); 1460 if (new_target_var != nullptr && MustAllocate(new_target_var)) { 1461 new_target_ = new_target_var; 1462 } 1463 1464 Variable* this_function_var = 1465 LookupLocal(ast_value_factory_->this_function_string()); 1466 if (this_function_var != nullptr && MustAllocate(this_function_var)) { 1467 this_function_ = this_function_var; 1468 } 1469 } 1470 1471 1472 void Scope::AllocateVariablesRecursively(Isolate* isolate) { 1473 if (!already_resolved()) { 1474 num_stack_slots_ = 0; 1475 } 1476 // Allocate variables for inner scopes. 1477 for (int i = 0; i < inner_scopes_.length(); i++) { 1478 inner_scopes_[i]->AllocateVariablesRecursively(isolate); 1479 } 1480 1481 // If scope is already resolved, we still need to allocate 1482 // variables in inner scopes which might not have been resolved yet. 1483 if (already_resolved()) return; 1484 // The number of slots required for variables. 1485 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1486 1487 // Allocate variables for this scope. 1488 // Parameters must be allocated first, if any. 1489 if (is_function_scope()) AllocateParameterLocals(isolate); 1490 if (has_this_declaration()) AllocateReceiver(); 1491 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); 1492 1493 // Force allocation of a context for this scope if necessary. For a 'with' 1494 // scope and for a function scope that makes an 'eval' call we need a context, 1495 // even if no local variables were statically allocated in the scope. 1496 // Likewise for modules. 1497 bool must_have_context = 1498 is_with_scope() || is_module_scope() || 1499 (is_function_scope() && calls_sloppy_eval()) || 1500 (is_block_scope() && is_declaration_scope() && calls_sloppy_eval()); 1501 1502 // If we didn't allocate any locals in the local context, then we only 1503 // need the minimal number of slots if we must have a context. 1504 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { 1505 num_heap_slots_ = 0; 1506 } 1507 1508 // Allocation done. 1509 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1510 } 1511 1512 1513 int Scope::StackLocalCount() const { 1514 return num_stack_slots() - 1515 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); 1516 } 1517 1518 1519 int Scope::ContextLocalCount() const { 1520 if (num_heap_slots() == 0) return 0; 1521 bool is_function_var_in_context = 1522 function_ != NULL && function_->proxy()->var()->IsContextSlot(); 1523 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - 1524 (is_function_var_in_context ? 1 : 0); 1525 } 1526 1527 1528 int Scope::ContextGlobalCount() const { return num_global_slots(); } 1529 1530 } // namespace internal 1531 } // namespace v8 1532