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.
7 #include "src/accessors.h"
8 #include "src/bootstrapper.h"
9 #include "src/messages.h"
10 #include "src/parser.h"
11 #include "src/scopeinfo.h"
12 #include "src/scopes.h"
17 // ----------------------------------------------------------------------------
18 // Implementation of LocalsMap
20 // Note: We are storing the handle locations as key values in the hash map.
21 // When inserting a new variable via Declare(), we rely on the fact that
22 // the handle location remains alive for the duration of that variable
23 // use. Because a Variable holding a handle with the same location exists
26 VariableMap::VariableMap(Zone* zone)
27 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
29 VariableMap::~VariableMap() {}
32 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name,
33 VariableMode mode, Variable::Kind kind,
34 InitializationFlag initialization_flag,
35 MaybeAssignedFlag maybe_assigned_flag,
36 int declaration_group_start) {
37 // AstRawStrings are unambiguous, i.e., the same string is always represented
38 // by the same AstRawString*.
39 // FIXME(marja): fix the type of Lookup.
41 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(),
42 ZoneAllocationPolicy(zone()));
43 if (p->value == NULL) {
44 // The variable has not been declared yet -> insert it.
45 DCHECK(p->key == name);
46 if (kind == Variable::CLASS) {
47 p->value = new (zone())
48 ClassVariable(scope, name, mode, initialization_flag,
49 maybe_assigned_flag, declaration_group_start);
51 p->value = new (zone()) Variable(
52 scope, name, mode, kind, initialization_flag, maybe_assigned_flag);
55 return reinterpret_cast<Variable*>(p->value);
59 Variable* VariableMap::Lookup(const AstRawString* name) {
60 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash());
62 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name);
63 DCHECK(p->value != NULL);
64 return reinterpret_cast<Variable*>(p->value);
70 // ----------------------------------------------------------------------------
71 // Implementation of Scope
73 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type,
74 AstValueFactory* ast_value_factory, FunctionKind function_kind)
75 : inner_scopes_(4, zone),
79 unresolved_(16, zone),
82 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL),
83 already_resolved_(false),
84 ast_value_factory_(ast_value_factory),
86 class_declaration_group_start_(-1) {
87 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(),
89 // The outermost scope must be a script scope.
90 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL);
91 DCHECK(!HasIllegalRedeclaration());
95 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type,
96 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory)
97 : inner_scopes_(4, zone),
101 unresolved_(16, zone),
103 module_descriptor_(NULL),
104 already_resolved_(true),
105 ast_value_factory_(value_factory),
107 class_declaration_group_start_(-1) {
108 SetDefaults(scope_type, NULL, scope_info);
109 if (!scope_info.is_null()) {
110 num_heap_slots_ = scope_info_->ContextLength();
112 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
113 num_heap_slots_ = Max(num_heap_slots_,
114 static_cast<int>(Context::MIN_CONTEXT_SLOTS));
115 AddInnerScope(inner_scope);
119 Scope::Scope(Zone* zone, Scope* inner_scope,
120 const AstRawString* catch_variable_name,
121 AstValueFactory* value_factory)
122 : inner_scopes_(1, zone),
126 unresolved_(0, zone),
128 module_descriptor_(NULL),
129 already_resolved_(true),
130 ast_value_factory_(value_factory),
132 class_declaration_group_start_(-1) {
133 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
134 AddInnerScope(inner_scope);
136 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
137 Variable* variable = variables_.Declare(this,
141 kCreatedInitialized);
142 AllocateHeapSlot(variable);
146 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
147 Handle<ScopeInfo> scope_info,
148 FunctionKind function_kind) {
149 outer_scope_ = outer_scope;
150 scope_type_ = scope_type;
151 is_declaration_scope_ =
152 is_eval_scope() || is_function_scope() ||
153 is_module_scope() || is_script_scope();
154 function_kind_ = function_kind;
155 scope_name_ = ast_value_factory_->empty_string();
158 new_target_ = nullptr;
160 arguments_ = nullptr;
161 this_function_ = nullptr;
162 illegal_redecl_ = nullptr;
163 scope_inside_with_ = false;
164 scope_contains_with_ = false;
165 scope_calls_eval_ = false;
166 scope_uses_arguments_ = false;
167 scope_uses_super_property_ = false;
169 asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
170 // Inherit the language mode from the parent scope.
171 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY;
172 outer_scope_calls_sloppy_eval_ = false;
173 inner_scope_calls_eval_ = false;
174 inner_scope_uses_arguments_ = false;
175 force_eager_compilation_ = false;
176 force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
177 ? outer_scope->has_forced_context_allocation() : false;
178 num_var_or_const_ = 0;
179 num_stack_slots_ = 0;
181 num_global_slots_ = 0;
184 rest_parameter_ = NULL;
186 scope_info_ = scope_info;
187 start_position_ = RelocInfo::kNoPosition;
188 end_position_ = RelocInfo::kNoPosition;
189 if (!scope_info.is_null()) {
190 scope_calls_eval_ = scope_info->CallsEval();
191 language_mode_ = scope_info->language_mode();
192 function_kind_ = scope_info->function_kind();
197 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
198 Context* context, Scope* script_scope) {
199 // Reconstruct the outer scope chain from a closure's context chain.
200 Scope* current_scope = NULL;
201 Scope* innermost_scope = NULL;
202 bool contains_with = false;
203 while (!context->IsNativeContext()) {
204 if (context->IsWithContext()) {
205 Scope* with_scope = new (zone)
206 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(),
207 script_scope->ast_value_factory_);
208 current_scope = with_scope;
209 // All the inner scopes are inside a with.
210 contains_with = true;
211 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
212 s->scope_inside_with_ = true;
214 } else if (context->IsScriptContext()) {
215 ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
216 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE,
217 Handle<ScopeInfo>(scope_info),
218 script_scope->ast_value_factory_);
219 } else if (context->IsModuleContext()) {
220 ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
221 current_scope = new (zone) Scope(zone, current_scope, MODULE_SCOPE,
222 Handle<ScopeInfo>(scope_info),
223 script_scope->ast_value_factory_);
224 } else if (context->IsFunctionContext()) {
225 ScopeInfo* scope_info = context->closure()->shared()->scope_info();
226 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE,
227 Handle<ScopeInfo>(scope_info),
228 script_scope->ast_value_factory_);
229 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true;
230 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true;
231 } else if (context->IsBlockContext()) {
232 ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
233 current_scope = new (zone)
234 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info),
235 script_scope->ast_value_factory_);
237 DCHECK(context->IsCatchContext());
238 String* name = String::cast(context->extension());
239 current_scope = new (zone) Scope(
241 script_scope->ast_value_factory_->GetString(Handle<String>(name)),
242 script_scope->ast_value_factory_);
244 if (contains_with) current_scope->RecordWithStatement();
245 if (innermost_scope == NULL) innermost_scope = current_scope;
247 // Forget about a with when we move to a context for a different function.
248 if (context->previous()->closure() != context->closure()) {
249 contains_with = false;
251 context = context->previous();
254 script_scope->AddInnerScope(current_scope);
255 script_scope->PropagateScopeInfo(false);
256 return (innermost_scope == NULL) ? script_scope : innermost_scope;
260 bool Scope::Analyze(ParseInfo* info) {
261 DCHECK(info->function() != NULL);
262 DCHECK(info->scope() == NULL);
263 Scope* scope = info->function()->scope();
266 // Traverse the scope tree up to the first unresolved scope or the global
267 // scope and start scope resolution and variable allocation from that scope.
268 while (!top->is_script_scope() &&
269 !top->outer_scope()->already_resolved()) {
270 top = top->outer_scope();
273 // Allocate the variables.
275 AstNodeFactory ast_node_factory(info->ast_value_factory());
276 if (!top->AllocateVariables(info, &ast_node_factory)) {
277 DCHECK(top->pending_error_handler_.has_pending_error());
278 top->pending_error_handler_.ThrowPendingError(info->isolate(),
285 bool native = info->isolate()->bootstrapper()->IsActive();
286 if (!info->shared_info().is_null()) {
287 Object* script = info->shared_info()->script();
288 native = script->IsScript() &&
289 Script::cast(script)->type()->value() == Script::TYPE_NATIVE;
292 if (native ? FLAG_print_builtin_scopes : FLAG_print_scopes) scope->Print();
295 info->set_scope(scope);
300 void Scope::Initialize() {
301 bool subclass_constructor = IsSubclassConstructor(function_kind_);
302 DCHECK(!already_resolved());
304 // Add this scope as a new inner scope of the outer scope.
305 if (outer_scope_ != NULL) {
306 outer_scope_->inner_scopes_.Add(this, zone());
307 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
309 scope_inside_with_ = is_with_scope();
312 // Declare convenience variables and the receiver.
313 if (is_declaration_scope() && has_this_declaration()) {
314 Variable* var = variables_.Declare(
315 this, ast_value_factory_->this_string(),
316 subclass_constructor ? CONST : VAR, Variable::THIS,
317 subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
321 if (is_function_scope() && !is_arrow_scope()) {
322 // Declare 'arguments' variable which exists in all non arrow functions.
323 // Note that it might never be accessed, in which case it won't be
324 // allocated during variable allocation.
325 variables_.Declare(this, ast_value_factory_->arguments_string(), VAR,
326 Variable::ARGUMENTS, kCreatedInitialized);
328 if (subclass_constructor || FLAG_harmony_new_target) {
329 variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
330 Variable::NORMAL, kCreatedInitialized);
333 if (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
334 IsAccessorFunction(function_kind_)) {
335 variables_.Declare(this, ast_value_factory_->this_function_string(),
336 CONST, Variable::NORMAL, kCreatedInitialized);
342 Scope* Scope::FinalizeBlockScope() {
343 DCHECK(is_block_scope());
344 DCHECK(temps_.is_empty());
345 DCHECK(params_.is_empty());
347 if (num_var_or_const() > 0) return this;
349 // Remove this scope from outer scope.
350 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
351 if (outer_scope_->inner_scopes_[i] == this) {
352 outer_scope_->inner_scopes_.Remove(i);
357 // Reparent inner scopes.
358 for (int i = 0; i < inner_scopes_.length(); i++) {
359 outer_scope()->AddInnerScope(inner_scopes_[i]);
362 // Move unresolved variables
363 for (int i = 0; i < unresolved_.length(); i++) {
364 outer_scope()->unresolved_.Add(unresolved_[i], zone());
367 // Propagate usage flags to outer scope.
368 if (uses_arguments()) outer_scope_->RecordArgumentsUsage();
369 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage();
370 if (scope_calls_eval_) outer_scope_->RecordEvalCall();
376 Variable* Scope::LookupLocal(const AstRawString* name) {
377 Variable* result = variables_.Lookup(name);
378 if (result != NULL || scope_info_.is_null()) {
381 Handle<String> name_handle = name->string();
382 // The Scope is backed up by ScopeInfo. This means it cannot operate in a
383 // heap-independent mode, and all strings must be internalized immediately. So
384 // it's ok to get the Handle<String> here.
385 // If we have a serialized scope info, we might find the variable there.
386 // There should be no local slot with the given name.
387 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope());
389 // Check context slot lookup.
391 VariableLocation location;
392 InitializationFlag init_flag;
393 MaybeAssignedFlag maybe_assigned_flag;
395 ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &location,
396 &init_flag, &maybe_assigned_flag);
399 index = scope_info_->ParameterIndex(*name_handle);
400 if (index < 0) return NULL;
403 location = VariableLocation::LOOKUP;
404 init_flag = kCreatedInitialized;
405 // Be conservative and flag parameters as maybe assigned. Better information
406 // would require ScopeInfo to serialize the maybe_assigned bit also for
408 maybe_assigned_flag = kMaybeAssigned;
410 DCHECK(location != VariableLocation::GLOBAL ||
411 (is_script_scope() && IsDeclaredVariableMode(mode) &&
412 !IsLexicalVariableMode(mode)));
415 Variable::Kind kind = Variable::NORMAL;
416 if (location == VariableLocation::CONTEXT &&
417 index == scope_info_->ReceiverContextSlotIndex()) {
418 kind = Variable::THIS;
420 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
421 // ARGUMENTS bindings as their corresponding Variable::Kind.
423 Variable* var = variables_.Declare(this, name, mode, kind, init_flag,
424 maybe_assigned_flag);
425 var->AllocateTo(location, index);
430 Variable* Scope::LookupFunctionVar(const AstRawString* name,
431 AstNodeFactory* factory) {
432 if (function_ != NULL && function_->proxy()->raw_name() == name) {
433 return function_->proxy()->var();
434 } else if (!scope_info_.is_null()) {
435 // If we are backed by a scope info, try to lookup the variable there.
437 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
438 if (index < 0) return NULL;
439 Variable* var = new (zone())
440 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized);
441 VariableProxy* proxy = factory->NewVariableProxy(var);
442 VariableDeclaration* declaration = factory->NewVariableDeclaration(
443 proxy, mode, this, RelocInfo::kNoPosition);
444 DeclareFunctionVar(declaration);
445 var->AllocateTo(VariableLocation::CONTEXT, index);
453 Variable* Scope::Lookup(const AstRawString* name) {
454 for (Scope* scope = this;
456 scope = scope->outer_scope()) {
457 Variable* var = scope->LookupLocal(name);
458 if (var != NULL) return var;
464 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode,
465 bool is_rest, bool* is_duplicate) {
466 DCHECK(!already_resolved());
467 DCHECK(is_function_scope());
470 if (!name->IsEmpty()) {
471 var = variables_.Declare(this, name, mode, Variable::NORMAL,
472 kCreatedInitialized);
473 // TODO(wingo): Avoid O(n^2) check.
474 *is_duplicate = IsDeclaredParameter(name);
477 Variable(this, name, TEMPORARY, Variable::NORMAL, kCreatedInitialized);
480 DCHECK_NULL(rest_parameter_);
481 rest_parameter_ = var;
482 rest_index_ = num_parameters();
484 params_.Add(var, zone());
489 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode,
490 InitializationFlag init_flag, Variable::Kind kind,
491 MaybeAssignedFlag maybe_assigned_flag,
492 int declaration_group_start) {
493 DCHECK(!already_resolved());
494 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
495 // introduces during variable allocation, and TEMPORARY variables are
496 // allocated via NewTemporary().
497 DCHECK(IsDeclaredVariableMode(mode));
499 return variables_.Declare(this, name, mode, kind, init_flag,
500 maybe_assigned_flag, declaration_group_start);
504 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) {
505 DCHECK(is_script_scope());
506 return variables_.Declare(this,
510 kCreatedInitialized);
514 void Scope::RemoveUnresolved(VariableProxy* var) {
515 // Most likely (always?) any variable we want to remove
516 // was just added before, so we search backwards.
517 for (int i = unresolved_.length(); i-- > 0;) {
518 if (unresolved_[i] == var) {
519 unresolved_.Remove(i);
526 Variable* Scope::NewTemporary(const AstRawString* name) {
527 DCHECK(!already_resolved());
528 Scope* scope = this->ClosureScope();
529 Variable* var = new(zone()) Variable(scope,
533 kCreatedInitialized);
534 scope->temps_.Add(var, zone());
539 void Scope::AddDeclaration(Declaration* declaration) {
540 decls_.Add(declaration, zone());
544 void Scope::SetIllegalRedeclaration(Expression* expression) {
545 // Record only the first illegal redeclaration.
546 if (!HasIllegalRedeclaration()) {
547 illegal_redecl_ = expression;
549 DCHECK(HasIllegalRedeclaration());
553 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
554 DCHECK(HasIllegalRedeclaration());
555 illegal_redecl_->Accept(visitor);
559 Declaration* Scope::CheckConflictingVarDeclarations() {
560 int length = decls_.length();
561 for (int i = 0; i < length; i++) {
562 Declaration* decl = decls_[i];
563 if (decl->mode() != VAR && !is_block_scope()) continue;
564 const AstRawString* name = decl->proxy()->raw_name();
566 // Iterate through all scopes until and including the declaration scope.
567 // If the declaration scope is a (declaration) block scope, also continue
568 // (that is to handle the special inner scope of functions with
569 // destructuring parameters, which may not shadow any variables from
570 // the surrounding function scope).
571 Scope* previous = NULL;
572 Scope* current = decl->scope();
573 // Lexical vs lexical conflicts within the same scope have already been
574 // captured in Parser::Declare. The only conflicts we still need to check
575 // are lexical vs VAR, or any declarations within a declaration block scope
576 // vs lexical declarations in its surrounding (function) scope.
577 if (decl->mode() != VAR) current = current->outer_scope_;
579 // There is a conflict if there exists a non-VAR binding.
580 Variable* other_var = current->variables_.Lookup(name);
581 if (other_var != NULL && other_var->mode() != VAR) {
585 current = current->outer_scope_;
586 } while (!previous->is_declaration_scope() || previous->is_block_scope());
594 VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
595 Variable* var() const { return var_; }
596 int order() const { return order_; }
597 static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
598 return a->order_ - b->order_;
607 void Scope::CollectStackAndContextLocals(
608 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals,
609 ZoneList<Variable*>* context_globals,
610 ZoneList<Variable*>* strong_mode_free_variables) {
611 DCHECK(stack_locals != NULL);
612 DCHECK(context_locals != NULL);
613 DCHECK(context_globals != NULL);
615 // Collect temporaries which are always allocated on the stack, unless the
616 // context as a whole has forced context allocation.
617 for (int i = 0; i < temps_.length(); i++) {
618 Variable* var = temps_[i];
619 if (var->is_used()) {
620 if (var->IsContextSlot()) {
621 DCHECK(has_forced_context_allocation());
622 context_locals->Add(var, zone());
624 DCHECK(var->IsStackLocal());
625 stack_locals->Add(var, zone());
630 // Collect declared local variables.
631 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
632 for (VariableMap::Entry* p = variables_.Start();
634 p = variables_.Next(p)) {
635 Variable* var = reinterpret_cast<Variable*>(p->value);
636 if (strong_mode_free_variables && var->has_strong_mode_reference() &&
637 var->mode() == DYNAMIC_GLOBAL) {
638 strong_mode_free_variables->Add(var, zone());
641 if (var->is_used()) {
642 vars.Add(VarAndOrder(var, p->order), zone());
645 vars.Sort(VarAndOrder::Compare);
646 int var_count = vars.length();
647 for (int i = 0; i < var_count; i++) {
648 Variable* var = vars[i].var();
649 if (var->IsStackLocal()) {
650 stack_locals->Add(var, zone());
651 } else if (var->IsContextSlot()) {
652 context_locals->Add(var, zone());
653 } else if (var->IsGlobalSlot()) {
654 context_globals->Add(var, zone());
660 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) {
661 // 1) Propagate scope information.
662 bool outer_scope_calls_sloppy_eval = false;
663 if (outer_scope_ != NULL) {
664 outer_scope_calls_sloppy_eval =
665 outer_scope_->outer_scope_calls_sloppy_eval() |
666 outer_scope_->calls_sloppy_eval();
668 PropagateScopeInfo(outer_scope_calls_sloppy_eval);
670 // 2) Allocate module instances.
671 if (FLAG_harmony_modules && is_script_scope()) {
672 DCHECK(num_modules_ == 0);
676 // 3) Resolve variables.
677 if (!ResolveVariablesRecursively(info, factory)) return false;
679 // 4) Allocate variables.
680 AllocateVariablesRecursively(info->isolate());
686 bool Scope::HasTrivialContext() const {
687 // A function scope has a trivial context if it always is the global
688 // context. We iteratively scan out the context chain to see if
689 // there is anything that makes this scope non-trivial; otherwise we
691 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
692 if (scope->is_eval_scope()) return false;
693 if (scope->scope_inside_with_) return false;
694 if (scope->ContextLocalCount() > 0) return false;
700 bool Scope::HasTrivialOuterContext() const {
701 Scope* outer = outer_scope_;
702 if (outer == NULL) return true;
703 // Note that the outer context may be trivial in general, but the current
704 // scope may be inside a 'with' statement in which case the outer context
705 // for this scope is not trivial.
706 return !scope_inside_with_ && outer->HasTrivialContext();
710 bool Scope::AllowsLazyParsing() const {
711 // If we are inside a block scope, we must parse eagerly to find out how
712 // to allocate variables on the block scope. At this point, declarations may
713 // not have yet been parsed.
714 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
715 if (scope->is_block_scope()) return false;
717 return AllowsLazyCompilation();
721 bool Scope::AllowsLazyCompilation() const { return !force_eager_compilation_; }
724 bool Scope::AllowsLazyCompilationWithoutContext() const {
725 return !force_eager_compilation_ && HasTrivialOuterContext();
729 int Scope::ContextChainLength(Scope* scope) {
731 for (Scope* s = this; s != scope; s = s->outer_scope_) {
732 DCHECK(s != NULL); // scope must be in the scope chain
733 if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
734 // Catch and module scopes always have heap slots.
735 DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0);
736 DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0);
742 Scope* Scope::DeclarationScope() {
744 while (!scope->is_declaration_scope()) {
745 scope = scope->outer_scope();
751 Scope* Scope::ClosureScope() {
753 while (!scope->is_declaration_scope() || scope->is_block_scope()) {
754 scope = scope->outer_scope();
760 Scope* Scope::ReceiverScope() {
762 while (!scope->is_script_scope() &&
763 (!scope->is_function_scope() || scope->is_arrow_scope())) {
764 scope = scope->outer_scope();
771 Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) {
772 if (scope_info_.is_null()) {
773 scope_info_ = ScopeInfo::Create(isolate, zone(), this);
779 void Scope::GetNestedScopeChain(Isolate* isolate,
780 List<Handle<ScopeInfo> >* chain, int position) {
781 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo(isolate)));
783 for (int i = 0; i < inner_scopes_.length(); i++) {
784 Scope* scope = inner_scopes_[i];
785 int beg_pos = scope->start_position();
786 int end_pos = scope->end_position();
787 DCHECK(beg_pos >= 0 && end_pos >= 0);
788 if (beg_pos <= position && position < end_pos) {
789 scope->GetNestedScopeChain(isolate, chain, position);
796 void Scope::ReportMessage(int start_position, int end_position,
797 MessageTemplate::Template message,
798 const AstRawString* arg) {
799 // Propagate the error to the topmost scope targeted by this scope analysis
802 while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) {
803 top = top->outer_scope();
806 top->pending_error_handler_.ReportMessageAt(start_position, end_position,
807 message, arg, kReferenceError);
812 static const char* Header(ScopeType scope_type) {
813 switch (scope_type) {
814 case EVAL_SCOPE: return "eval";
815 case FUNCTION_SCOPE: return "function";
816 case MODULE_SCOPE: return "module";
817 case SCRIPT_SCOPE: return "global";
818 case CATCH_SCOPE: return "catch";
819 case BLOCK_SCOPE: return "block";
820 case WITH_SCOPE: return "with";
821 case ARROW_SCOPE: return "arrow";
828 static void Indent(int n, const char* str) {
829 PrintF("%*s%s", n, "", str);
833 static void PrintName(const AstRawString* name) {
834 PrintF("%.*s", name->length(), name->raw_data());
838 static void PrintLocation(Variable* var) {
839 switch (var->location()) {
840 case VariableLocation::UNALLOCATED:
842 case VariableLocation::PARAMETER:
843 PrintF("parameter[%d]", var->index());
845 case VariableLocation::LOCAL:
846 PrintF("local[%d]", var->index());
848 case VariableLocation::CONTEXT:
849 PrintF("context[%d]", var->index());
851 case VariableLocation::GLOBAL:
852 PrintF("global[%d]", var->index());
854 case VariableLocation::LOOKUP:
861 static void PrintVar(int indent, Variable* var) {
862 if (var->is_used() || !var->IsUnallocated()) {
863 Indent(indent, Variable::Mode2String(var->mode()));
865 PrintName(var->raw_name());
868 bool comma = !var->IsUnallocated();
869 if (var->has_forced_context_allocation()) {
870 if (comma) PrintF(", ");
871 PrintF("forced context allocation");
874 if (var->maybe_assigned() == kMaybeAssigned) {
875 if (comma) PrintF(", ");
876 PrintF("maybe assigned");
883 static void PrintMap(int indent, VariableMap* map) {
884 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
885 Variable* var = reinterpret_cast<Variable*>(p->value);
887 Indent(indent, "<?>\n");
889 PrintVar(indent, var);
895 void Scope::Print(int n) {
896 int n0 = (n > 0 ? n : 0);
897 int n1 = n0 + 2; // indentation
900 Indent(n0, Header(scope_type_));
901 if (!scope_name_->IsEmpty()) {
903 PrintName(scope_name_);
906 // Print parameters, if any.
907 if (is_function_scope()) {
909 for (int i = 0; i < params_.length(); i++) {
910 if (i > 0) PrintF(", ");
911 PrintName(params_[i]->raw_name());
916 PrintF(" { // (%d, %d)\n", start_position(), end_position());
918 // Function name, if any (named function literals, only).
919 if (function_ != NULL) {
920 Indent(n1, "// (local) function name: ");
921 PrintName(function_->proxy()->raw_name());
926 if (HasTrivialOuterContext()) {
927 Indent(n1, "// scope has trivial outer context\n");
929 if (is_strong(language_mode())) {
930 Indent(n1, "// strong mode scope\n");
931 } else if (is_strict(language_mode())) {
932 Indent(n1, "// strict mode scope\n");
934 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
935 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
936 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
937 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
938 if (scope_uses_super_property_)
939 Indent(n1, "// scope uses 'super' property\n");
940 if (inner_scope_uses_arguments_) {
941 Indent(n1, "// inner scope uses 'arguments'\n");
943 if (outer_scope_calls_sloppy_eval_) {
944 Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
946 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
947 if (num_stack_slots_ > 0) {
949 PrintF("%d stack slots\n", num_stack_slots_);
951 if (num_heap_slots_ > 0) {
953 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_,
958 if (function_ != NULL) {
959 Indent(n1, "// function var:\n");
960 PrintVar(n1, function_->proxy()->var());
963 if (temps_.length() > 0) {
964 Indent(n1, "// temporary vars:\n");
965 for (int i = 0; i < temps_.length(); i++) {
966 PrintVar(n1, temps_[i]);
970 if (variables_.Start() != NULL) {
971 Indent(n1, "// local vars:\n");
972 PrintMap(n1, &variables_);
975 if (dynamics_ != NULL) {
976 Indent(n1, "// dynamic vars:\n");
977 PrintMap(n1, dynamics_->GetMap(DYNAMIC));
978 PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
979 PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
982 // Print inner scopes (disable by providing negative n).
984 for (int i = 0; i < inner_scopes_.length(); i++) {
986 inner_scopes_[i]->Print(n1);
995 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
996 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
997 VariableMap* map = dynamics_->GetMap(mode);
998 Variable* var = map->Lookup(name);
1000 // Declare a new non-local.
1001 InitializationFlag init_flag = (mode == VAR)
1002 ? kCreatedInitialized : kNeedsInitialization;
1003 var = map->Declare(NULL,
1008 // Allocate it by giving it a dynamic lookup.
1009 var->AllocateTo(VariableLocation::LOOKUP, -1);
1015 Variable* Scope::LookupRecursive(VariableProxy* proxy,
1016 BindingKind* binding_kind,
1017 AstNodeFactory* factory) {
1018 DCHECK(binding_kind != NULL);
1019 if (already_resolved() && is_with_scope()) {
1020 // Short-cut: if the scope is deserialized from a scope info, variable
1021 // allocation is already fixed. We can simply return with dynamic lookup.
1022 *binding_kind = DYNAMIC_LOOKUP;
1026 // Try to find the variable in this scope.
1027 Variable* var = LookupLocal(proxy->raw_name());
1029 // We found a variable and we are done. (Even if there is an 'eval' in
1030 // this scope which introduces the same variable again, the resulting
1031 // variable remains the same.)
1033 *binding_kind = BOUND;
1037 // We did not find a variable locally. Check against the function variable,
1038 // if any. We can do this for all scopes, since the function variable is
1039 // only present - if at all - for function scopes.
1040 *binding_kind = UNBOUND;
1041 var = LookupFunctionVar(proxy->raw_name(), factory);
1043 *binding_kind = BOUND;
1044 } else if (outer_scope_ != NULL) {
1045 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory);
1046 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
1047 var->ForceContextAllocation();
1050 DCHECK(is_script_scope());
1053 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
1054 // TODO(wingo): There are other variables in this category; add them.
1055 bool name_can_be_shadowed = var == nullptr || !var->is_this();
1057 if (is_with_scope() && name_can_be_shadowed) {
1058 DCHECK(!already_resolved());
1059 // The current scope is a with scope, so the variable binding can not be
1060 // statically resolved. However, note that it was necessary to do a lookup
1061 // in the outer scope anyway, because if a binding exists in an outer scope,
1062 // the associated variable has to be marked as potentially being accessed
1063 // from inside of an inner with scope (the property may not be in the 'with'
1065 if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned();
1066 *binding_kind = DYNAMIC_LOOKUP;
1068 } else if (calls_sloppy_eval() && name_can_be_shadowed) {
1069 // A variable binding may have been found in an outer scope, but the current
1070 // scope makes a sloppy 'eval' call, so the found variable may not be
1071 // the correct one (the 'eval' may introduce a binding with the same name).
1072 // In that case, change the lookup result to reflect this situation.
1073 if (*binding_kind == BOUND) {
1074 *binding_kind = BOUND_EVAL_SHADOWED;
1075 } else if (*binding_kind == UNBOUND) {
1076 *binding_kind = UNBOUND_EVAL_SHADOWED;
1083 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy,
1084 AstNodeFactory* factory) {
1085 DCHECK(info->script_scope()->is_script_scope());
1087 // If the proxy is already resolved there's nothing to do
1088 // (functions and consts may be resolved by the parser).
1089 if (proxy->is_resolved()) return true;
1091 // Otherwise, try to resolve the variable.
1092 BindingKind binding_kind;
1093 Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1094 switch (binding_kind) {
1096 // We found a variable binding.
1097 if (is_strong(language_mode())) {
1098 if (!CheckStrongModeDeclaration(proxy, var)) return false;
1102 case BOUND_EVAL_SHADOWED:
1103 // We either found a variable binding that might be shadowed by eval or
1104 // gave up on it (e.g. by encountering a local with the same in the outer
1105 // scope which was not promoted to a context, this can happen if we use
1106 // debugger to evaluate arbitrary expressions at a break point).
1107 if (var->IsGlobalObjectProperty()) {
1108 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1109 } else if (var->is_dynamic()) {
1110 var = NonLocal(proxy->raw_name(), DYNAMIC);
1112 Variable* invalidated = var;
1113 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
1114 var->set_local_if_not_shadowed(invalidated);
1119 // No binding has been found. Declare a variable on the global object.
1120 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name());
1123 case UNBOUND_EVAL_SHADOWED:
1124 // No binding has been found. But some scope makes a sloppy 'eval' call.
1125 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
1128 case DYNAMIC_LOOKUP:
1129 // The variable could not be resolved statically.
1130 var = NonLocal(proxy->raw_name(), DYNAMIC);
1134 DCHECK(var != NULL);
1135 if (proxy->is_assigned()) var->set_maybe_assigned();
1137 if (is_strong(language_mode())) {
1138 // Record that the variable is referred to from strong mode. Also, record
1140 var->RecordStrongModeReference(proxy->position(), proxy->end_position());
1149 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) {
1150 // Check for declaration-after use (for variables) in strong mode. Note that
1151 // we can only do this in the case where we have seen the declaration. And we
1152 // always allow referencing functions (for now).
1154 // This might happen during lazy compilation; we don't keep track of
1155 // initializer positions for variables stored in ScopeInfo, so we cannot check
1156 // bindings against them. TODO(marja, rossberg): remove this hack.
1157 if (var->initializer_position() == RelocInfo::kNoPosition) return true;
1159 // Allow referencing the class name from methods of that class, even though
1160 // the initializer position for class names is only after the body.
1161 Scope* scope = this;
1163 if (scope->ClassVariableForMethod() == var) return true;
1164 scope = scope->outer_scope();
1167 // Allow references from methods to classes declared later, if we detect no
1168 // problematic dependency cycles. Note that we can be inside multiple methods
1169 // at the same time, and it's enough if we find one where the reference is
1171 if (var->is_class() &&
1172 var->AsClassVariable()->declaration_group_start() >= 0) {
1173 for (scope = this; scope && scope != var->scope();
1174 scope = scope->outer_scope()) {
1175 ClassVariable* class_var = scope->ClassVariableForMethod();
1176 // A method is referring to some other class, possibly declared
1177 // later. Referring to a class declared earlier is always OK and covered
1178 // by the code outside this if. Here we only need to allow special cases
1179 // for referring to a class which is declared later.
1181 // Referring to a class C declared later is OK under the following
1184 // 1. The class declarations are in a consecutive group with no other
1185 // declarations or statements in between, and
1187 // 2. There is no dependency cycle where the first edge is an
1188 // initialization time dependency (computed property name or extends
1189 // clause) from C to something that depends on this class directly or
1192 class_var->declaration_group_start() ==
1193 var->AsClassVariable()->declaration_group_start()) {
1197 // TODO(marja,rossberg): implement the dependency cycle detection. Here we
1198 // undershoot the target and allow referring to any class in the same
1199 // consectuive declaration group.
1201 // The cycle detection can work roughly like this: 1) detect init-time
1202 // references here (they are free variables which are inside the class
1203 // scope but not inside a method scope - no parser changes needed to
1204 // detect them) 2) if we encounter an init-time reference here, allow it,
1205 // but record it for a later dependency cycle check 3) also record
1206 // non-init-time references here 4) after scope analysis is done, analyse
1207 // the dependency cycles: an illegal cycle is one starting with an
1208 // init-time reference and leading back to the starting point with either
1209 // non-init-time and init-time references.
1213 // If both the use and the declaration are inside an eval scope (possibly
1214 // indirectly), or one of them is, we need to check whether they are inside
1215 // the same eval scope or different ones.
1217 // TODO(marja,rossberg): Detect errors across different evals (depends on the
1218 // future of eval in strong mode).
1219 const Scope* eval_for_use = NearestOuterEvalScope();
1220 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope();
1222 if (proxy->position() != RelocInfo::kNoPosition &&
1223 proxy->position() < var->initializer_position() && !var->is_function() &&
1224 eval_for_use == eval_for_declaration) {
1225 DCHECK(proxy->end_position() != RelocInfo::kNoPosition);
1226 ReportMessage(proxy->position(), proxy->end_position(),
1227 MessageTemplate::kStrongUseBeforeDeclaration,
1235 ClassVariable* Scope::ClassVariableForMethod() const {
1236 // TODO(marja, rossberg): This fails to find a class variable in the following
1238 // let A = class { ... }
1239 // It needs to be investigated whether this causes any practical problems.
1240 if (!is_function_scope()) return nullptr;
1241 if (IsInObjectLiteral(function_kind_)) return nullptr;
1242 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) &&
1243 !IsAccessorFunction(function_kind_)) {
1246 DCHECK_NOT_NULL(outer_scope_);
1247 // The class scope contains at most one variable, the class name.
1248 DCHECK(outer_scope_->variables_.occupancy() <= 1);
1249 if (outer_scope_->variables_.occupancy() == 0) return nullptr;
1250 VariableMap::Entry* p = outer_scope_->variables_.Start();
1251 Variable* var = reinterpret_cast<Variable*>(p->value);
1252 if (!var->is_class()) return nullptr;
1253 return var->AsClassVariable();
1257 bool Scope::ResolveVariablesRecursively(ParseInfo* info,
1258 AstNodeFactory* factory) {
1259 DCHECK(info->script_scope()->is_script_scope());
1261 // Resolve unresolved variables for this scope.
1262 for (int i = 0; i < unresolved_.length(); i++) {
1263 if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1266 // Resolve unresolved variables for inner scopes.
1267 for (int i = 0; i < inner_scopes_.length(); i++) {
1268 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1276 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
1277 if (outer_scope_calls_sloppy_eval) {
1278 outer_scope_calls_sloppy_eval_ = true;
1281 bool calls_sloppy_eval =
1282 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
1283 for (int i = 0; i < inner_scopes_.length(); i++) {
1284 Scope* inner = inner_scopes_[i];
1285 inner->PropagateScopeInfo(calls_sloppy_eval);
1286 if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) {
1287 inner_scope_calls_eval_ = true;
1289 // If the inner scope is an arrow function, propagate the flags tracking
1290 // usage of arguments/super/this, but do not propagate them out from normal
1292 if (!inner->is_function_scope() || inner->is_arrow_scope()) {
1293 if (inner->scope_uses_arguments_ || inner->inner_scope_uses_arguments_) {
1294 inner_scope_uses_arguments_ = true;
1297 if (inner->force_eager_compilation_) {
1298 force_eager_compilation_ = true;
1300 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) {
1301 inner->asm_function_ = true;
1307 bool Scope::MustAllocate(Variable* var) {
1308 // Give var a read/write use if there is a chance it might be accessed
1309 // via an eval() call. This is only possible if the variable has a
1311 if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
1312 (var->has_forced_context_allocation() || scope_calls_eval_ ||
1313 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
1314 is_block_scope() || is_module_scope() || is_script_scope())) {
1316 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
1318 // Global variables do not need to be allocated.
1319 return !var->IsGlobalObjectProperty() && var->is_used();
1323 bool Scope::MustAllocateInContext(Variable* var) {
1324 // If var is accessed from an inner scope, or if there is a possibility
1325 // that it might be accessed from the current or an inner scope (through
1326 // an eval() call or a runtime with lookup), it must be allocated in the
1329 // Exceptions: If the scope as a whole has forced context allocation, all
1330 // variables will have context allocation, even temporaries. Otherwise
1331 // temporary variables are always stack-allocated. Catch-bound variables are
1332 // always context-allocated.
1333 if (has_forced_context_allocation()) return true;
1334 if (var->mode() == TEMPORARY) return false;
1335 if (is_catch_scope() || is_module_scope()) return true;
1336 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true;
1337 return var->has_forced_context_allocation() ||
1338 scope_calls_eval_ ||
1339 inner_scope_calls_eval_ ||
1340 scope_contains_with_;
1344 bool Scope::HasArgumentsParameter(Isolate* isolate) {
1345 for (int i = 0; i < params_.length(); i++) {
1346 if (params_[i]->name().is_identical_to(
1347 isolate->factory()->arguments_string())) {
1355 void Scope::AllocateStackSlot(Variable* var) {
1356 if (is_block_scope()) {
1357 outer_scope()->DeclarationScope()->AllocateStackSlot(var);
1359 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++);
1364 void Scope::AllocateHeapSlot(Variable* var) {
1365 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++);
1369 void Scope::AllocateParameterLocals(Isolate* isolate) {
1370 DCHECK(is_function_scope());
1371 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
1372 // Functions have 'arguments' declared implicitly in all non arrow functions.
1373 DCHECK(arguments != nullptr || is_arrow_scope());
1375 bool uses_sloppy_arguments = false;
1377 if (arguments != nullptr && MustAllocate(arguments) &&
1378 !HasArgumentsParameter(isolate)) {
1379 // 'arguments' is used. Unless there is also a parameter called
1380 // 'arguments', we must be conservative and allocate all parameters to
1381 // the context assuming they will be captured by the arguments object.
1382 // If we have a parameter named 'arguments', a (new) value is always
1383 // assigned to it via the function invocation. Then 'arguments' denotes
1384 // that specific parameter value and cannot be used to access the
1385 // parameters, which is why we don't need to allocate an arguments
1386 // object in that case.
1388 // We are using 'arguments'. Tell the code generator that is needs to
1389 // allocate the arguments object by setting 'arguments_'.
1390 arguments_ = arguments;
1392 // In strict mode 'arguments' does not alias formal parameters.
1393 // Therefore in strict mode we allocate parameters as if 'arguments'
1395 uses_sloppy_arguments = is_sloppy(language_mode());
1398 if (rest_parameter_ && !MustAllocate(rest_parameter_)) {
1399 rest_parameter_ = NULL;
1402 // The same parameter may occur multiple times in the parameters_ list.
1403 // If it does, and if it is not copied into the context object, it must
1404 // receive the highest parameter index for that parameter; thus iteration
1405 // order is relevant!
1406 for (int i = params_.length() - 1; i >= 0; --i) {
1407 Variable* var = params_[i];
1408 if (var == rest_parameter_) continue;
1410 DCHECK(var->scope() == this);
1411 if (uses_sloppy_arguments || has_forced_context_allocation()) {
1412 // Force context allocation of the parameter.
1413 var->ForceContextAllocation();
1415 AllocateParameter(var, i);
1420 void Scope::AllocateParameter(Variable* var, int index) {
1421 if (MustAllocate(var)) {
1422 if (MustAllocateInContext(var)) {
1423 DCHECK(var->IsUnallocated() || var->IsContextSlot());
1424 if (var->IsUnallocated()) {
1425 AllocateHeapSlot(var);
1428 DCHECK(var->IsUnallocated() || var->IsParameter());
1429 if (var->IsUnallocated()) {
1430 var->AllocateTo(VariableLocation::PARAMETER, index);
1434 DCHECK(!var->IsGlobalSlot());
1439 void Scope::AllocateReceiver() {
1440 DCHECK_NOT_NULL(receiver());
1441 DCHECK_EQ(receiver()->scope(), this);
1443 if (has_forced_context_allocation()) {
1444 // Force context allocation of the receiver.
1445 receiver()->ForceContextAllocation();
1447 AllocateParameter(receiver(), -1);
1451 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) {
1452 DCHECK(var->scope() == this);
1453 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) ||
1454 !var->IsStackLocal());
1455 if (var->IsUnallocated() && MustAllocate(var)) {
1456 if (MustAllocateInContext(var)) {
1457 AllocateHeapSlot(var);
1459 AllocateStackSlot(var);
1465 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) {
1466 DCHECK(var->scope() == this);
1467 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) ||
1468 !var->IsStackLocal());
1469 if (var->IsUnallocated()) {
1470 if (var->IsStaticGlobalObjectProperty()) {
1471 DCHECK_EQ(-1, var->index());
1472 DCHECK(var->name()->IsString());
1473 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_);
1474 num_global_slots_++;
1475 // Each global variable occupies two slots in the context: for reads
1477 num_heap_slots_ += 2;
1479 // There must be only DYNAMIC_GLOBAL in the script scope.
1480 DCHECK(!is_script_scope() || DYNAMIC_GLOBAL == var->mode());
1486 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) {
1487 // All variables that have no rewrite yet are non-parameter locals.
1488 for (int i = 0; i < temps_.length(); i++) {
1489 AllocateNonParameterLocal(isolate, temps_[i]);
1492 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
1493 for (VariableMap::Entry* p = variables_.Start();
1495 p = variables_.Next(p)) {
1496 Variable* var = reinterpret_cast<Variable*>(p->value);
1497 vars.Add(VarAndOrder(var, p->order), zone());
1499 vars.Sort(VarAndOrder::Compare);
1500 int var_count = vars.length();
1501 for (int i = 0; i < var_count; i++) {
1502 AllocateNonParameterLocal(isolate, vars[i].var());
1505 if (FLAG_global_var_shortcuts) {
1506 for (int i = 0; i < var_count; i++) {
1507 AllocateDeclaredGlobal(isolate, vars[i].var());
1511 // For now, function_ must be allocated at the very end. If it gets
1512 // allocated in the context, it must be the last slot in the context,
1513 // because of the current ScopeInfo implementation (see
1514 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1515 if (function_ != nullptr) {
1516 AllocateNonParameterLocal(isolate, function_->proxy()->var());
1519 if (rest_parameter_ != nullptr) {
1520 AllocateNonParameterLocal(isolate, rest_parameter_);
1523 Variable* new_target_var =
1524 LookupLocal(ast_value_factory_->new_target_string());
1525 if (new_target_var != nullptr && MustAllocate(new_target_var)) {
1526 new_target_ = new_target_var;
1529 Variable* this_function_var =
1530 LookupLocal(ast_value_factory_->this_function_string());
1531 if (this_function_var != nullptr && MustAllocate(this_function_var)) {
1532 this_function_ = this_function_var;
1537 void Scope::AllocateVariablesRecursively(Isolate* isolate) {
1538 if (!already_resolved()) {
1539 num_stack_slots_ = 0;
1541 // Allocate variables for inner scopes.
1542 for (int i = 0; i < inner_scopes_.length(); i++) {
1543 inner_scopes_[i]->AllocateVariablesRecursively(isolate);
1546 // If scope is already resolved, we still need to allocate
1547 // variables in inner scopes which might not had been resolved yet.
1548 if (already_resolved()) return;
1549 // The number of slots required for variables.
1550 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1552 // Allocate variables for this scope.
1553 // Parameters must be allocated first, if any.
1554 if (is_function_scope()) AllocateParameterLocals(isolate);
1555 if (has_this_declaration()) AllocateReceiver();
1556 AllocateNonParameterLocalsAndDeclaredGlobals(isolate);
1558 // Force allocation of a context for this scope if necessary. For a 'with'
1559 // scope and for a function scope that makes an 'eval' call we need a context,
1560 // even if no local variables were statically allocated in the scope.
1561 // Likewise for modules.
1562 bool must_have_context = is_with_scope() || is_module_scope() ||
1563 (is_function_scope() && calls_sloppy_eval());
1565 // If we didn't allocate any locals in the local context, then we only
1566 // need the minimal number of slots if we must have a context.
1567 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1568 num_heap_slots_ = 0;
1572 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1576 void Scope::AllocateModules() {
1577 DCHECK(is_script_scope());
1578 DCHECK(!already_resolved());
1579 for (int i = 0; i < inner_scopes_.length(); i++) {
1580 Scope* scope = inner_scopes_.at(i);
1581 if (scope->is_module_scope()) {
1582 DCHECK(!scope->already_resolved());
1583 DCHECK(scope->module_descriptor_->IsFrozen());
1584 DCHECK_NULL(scope->module_var_);
1585 scope->module_var_ =
1586 NewTemporary(ast_value_factory_->dot_module_string());
1593 int Scope::StackLocalCount() const {
1594 return num_stack_slots() -
1595 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1599 int Scope::ContextLocalCount() const {
1600 if (num_heap_slots() == 0) return 0;
1601 bool is_function_var_in_context =
1602 function_ != NULL && function_->proxy()->var()->IsContextSlot();
1603 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1604 2 * num_global_slots() - (is_function_var_in_context ? 1 : 0);
1608 int Scope::ContextGlobalCount() const { return num_global_slots(); }
1609 } // namespace internal