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