• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/v8.h"
6 
7 #include "src/scopes.h"
8 
9 #include "src/accessors.h"
10 #include "src/bootstrapper.h"
11 #include "src/compiler.h"
12 #include "src/messages.h"
13 #include "src/scopeinfo.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // ----------------------------------------------------------------------------
19 // Implementation of LocalsMap
20 //
21 // Note: We are storing the handle locations as key values in the hash map.
22 //       When inserting a new variable via Declare(), we rely on the fact that
23 //       the handle location remains alive for the duration of that variable
24 //       use. Because a Variable holding a handle with the same location exists
25 //       this is ensured.
26 
Match(void * key1,void * key2)27 static bool Match(void* key1, void* key2) {
28   String* name1 = *reinterpret_cast<String**>(key1);
29   String* name2 = *reinterpret_cast<String**>(key2);
30   ASSERT(name1->IsInternalizedString());
31   ASSERT(name2->IsInternalizedString());
32   return name1 == name2;
33 }
34 
35 
VariableMap(Zone * zone)36 VariableMap::VariableMap(Zone* zone)
37     : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
38       zone_(zone) {}
~VariableMap()39 VariableMap::~VariableMap() {}
40 
41 
Declare(Scope * scope,Handle<String> name,VariableMode mode,bool is_valid_lhs,Variable::Kind kind,InitializationFlag initialization_flag,Interface * interface)42 Variable* VariableMap::Declare(
43     Scope* scope,
44     Handle<String> name,
45     VariableMode mode,
46     bool is_valid_lhs,
47     Variable::Kind kind,
48     InitializationFlag initialization_flag,
49     Interface* interface) {
50   Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
51                                  ZoneAllocationPolicy(zone()));
52   if (p->value == NULL) {
53     // The variable has not been declared yet -> insert it.
54     ASSERT(p->key == name.location());
55     p->value = new(zone()) Variable(scope,
56                                     name,
57                                     mode,
58                                     is_valid_lhs,
59                                     kind,
60                                     initialization_flag,
61                                     interface);
62   }
63   return reinterpret_cast<Variable*>(p->value);
64 }
65 
66 
Lookup(Handle<String> name)67 Variable* VariableMap::Lookup(Handle<String> name) {
68   Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
69                                  ZoneAllocationPolicy(NULL));
70   if (p != NULL) {
71     ASSERT(*reinterpret_cast<String**>(p->key) == *name);
72     ASSERT(p->value != NULL);
73     return reinterpret_cast<Variable*>(p->value);
74   }
75   return NULL;
76 }
77 
78 
79 // ----------------------------------------------------------------------------
80 // Implementation of Scope
81 
Scope(Scope * outer_scope,ScopeType scope_type,Zone * zone)82 Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
83     : isolate_(zone->isolate()),
84       inner_scopes_(4, zone),
85       variables_(zone),
86       internals_(4, zone),
87       temps_(4, zone),
88       params_(4, zone),
89       unresolved_(16, zone),
90       decls_(4, zone),
91       interface_(FLAG_harmony_modules &&
92                  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
93                      ? Interface::NewModule(zone) : NULL),
94       already_resolved_(false),
95       zone_(zone) {
96   SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
97   // The outermost scope must be a global scope.
98   ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL);
99   ASSERT(!HasIllegalRedeclaration());
100 }
101 
102 
Scope(Scope * inner_scope,ScopeType scope_type,Handle<ScopeInfo> scope_info,Zone * zone)103 Scope::Scope(Scope* inner_scope,
104              ScopeType scope_type,
105              Handle<ScopeInfo> scope_info,
106              Zone* zone)
107     : isolate_(zone->isolate()),
108       inner_scopes_(4, zone),
109       variables_(zone),
110       internals_(4, zone),
111       temps_(4, zone),
112       params_(4, zone),
113       unresolved_(16, zone),
114       decls_(4, zone),
115       interface_(NULL),
116       already_resolved_(true),
117       zone_(zone) {
118   SetDefaults(scope_type, NULL, scope_info);
119   if (!scope_info.is_null()) {
120     num_heap_slots_ = scope_info_->ContextLength();
121   }
122   // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
123   num_heap_slots_ = Max(num_heap_slots_,
124                         static_cast<int>(Context::MIN_CONTEXT_SLOTS));
125   AddInnerScope(inner_scope);
126 }
127 
128 
Scope(Scope * inner_scope,Handle<String> catch_variable_name,Zone * zone)129 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
130     : isolate_(zone->isolate()),
131       inner_scopes_(1, zone),
132       variables_(zone),
133       internals_(0, zone),
134       temps_(0, zone),
135       params_(0, zone),
136       unresolved_(0, zone),
137       decls_(0, zone),
138       interface_(NULL),
139       already_resolved_(true),
140       zone_(zone) {
141   SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
142   AddInnerScope(inner_scope);
143   ++num_var_or_const_;
144   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
145   Variable* variable = variables_.Declare(this,
146                                           catch_variable_name,
147                                           VAR,
148                                           true,  // Valid left-hand side.
149                                           Variable::NORMAL,
150                                           kCreatedInitialized);
151   AllocateHeapSlot(variable);
152 }
153 
154 
SetDefaults(ScopeType scope_type,Scope * outer_scope,Handle<ScopeInfo> scope_info)155 void Scope::SetDefaults(ScopeType scope_type,
156                         Scope* outer_scope,
157                         Handle<ScopeInfo> scope_info) {
158   outer_scope_ = outer_scope;
159   scope_type_ = scope_type;
160   scope_name_ = isolate_->factory()->empty_string();
161   dynamics_ = NULL;
162   receiver_ = NULL;
163   function_ = NULL;
164   arguments_ = NULL;
165   illegal_redecl_ = NULL;
166   scope_inside_with_ = false;
167   scope_contains_with_ = false;
168   scope_calls_eval_ = false;
169   // Inherit the strict mode from the parent scope.
170   strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
171   outer_scope_calls_sloppy_eval_ = false;
172   inner_scope_calls_eval_ = false;
173   force_eager_compilation_ = false;
174   force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
175       ? outer_scope->has_forced_context_allocation() : false;
176   num_var_or_const_ = 0;
177   num_stack_slots_ = 0;
178   num_heap_slots_ = 0;
179   num_modules_ = 0;
180   module_var_ = NULL,
181   scope_info_ = scope_info;
182   start_position_ = RelocInfo::kNoPosition;
183   end_position_ = RelocInfo::kNoPosition;
184   if (!scope_info.is_null()) {
185     scope_calls_eval_ = scope_info->CallsEval();
186     strict_mode_ = scope_info->strict_mode();
187   }
188 }
189 
190 
DeserializeScopeChain(Context * context,Scope * global_scope,Zone * zone)191 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
192                                     Zone* zone) {
193   // Reconstruct the outer scope chain from a closure's context chain.
194   Scope* current_scope = NULL;
195   Scope* innermost_scope = NULL;
196   bool contains_with = false;
197   while (!context->IsNativeContext()) {
198     if (context->IsWithContext()) {
199       Scope* with_scope = new(zone) Scope(current_scope,
200                                           WITH_SCOPE,
201                                           Handle<ScopeInfo>::null(),
202                                           zone);
203       current_scope = with_scope;
204       // All the inner scopes are inside a with.
205       contains_with = true;
206       for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
207         s->scope_inside_with_ = true;
208       }
209     } else if (context->IsGlobalContext()) {
210       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
211       current_scope = new(zone) Scope(current_scope,
212                                       GLOBAL_SCOPE,
213                                       Handle<ScopeInfo>(scope_info),
214                                       zone);
215     } else if (context->IsModuleContext()) {
216       ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
217       current_scope = new(zone) Scope(current_scope,
218                                       MODULE_SCOPE,
219                                       Handle<ScopeInfo>(scope_info),
220                                       zone);
221     } else if (context->IsFunctionContext()) {
222       ScopeInfo* scope_info = context->closure()->shared()->scope_info();
223       current_scope = new(zone) Scope(current_scope,
224                                       FUNCTION_SCOPE,
225                                       Handle<ScopeInfo>(scope_info),
226                                       zone);
227     } else if (context->IsBlockContext()) {
228       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
229       current_scope = new(zone) Scope(current_scope,
230                                       BLOCK_SCOPE,
231                                       Handle<ScopeInfo>(scope_info),
232                                       zone);
233     } else {
234       ASSERT(context->IsCatchContext());
235       String* name = String::cast(context->extension());
236       current_scope = new(zone) Scope(
237           current_scope, Handle<String>(name), zone);
238     }
239     if (contains_with) current_scope->RecordWithStatement();
240     if (innermost_scope == NULL) innermost_scope = current_scope;
241 
242     // Forget about a with when we move to a context for a different function.
243     if (context->previous()->closure() != context->closure()) {
244       contains_with = false;
245     }
246     context = context->previous();
247   }
248 
249   global_scope->AddInnerScope(current_scope);
250   global_scope->PropagateScopeInfo(false);
251   return (innermost_scope == NULL) ? global_scope : innermost_scope;
252 }
253 
254 
Analyze(CompilationInfo * info)255 bool Scope::Analyze(CompilationInfo* info) {
256   ASSERT(info->function() != NULL);
257   Scope* scope = info->function()->scope();
258   Scope* top = scope;
259 
260   // Traverse the scope tree up to the first unresolved scope or the global
261   // scope and start scope resolution and variable allocation from that scope.
262   while (!top->is_global_scope() &&
263          !top->outer_scope()->already_resolved()) {
264     top = top->outer_scope();
265   }
266 
267   // Allocate the variables.
268   {
269     AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
270     if (!top->AllocateVariables(info, &ast_node_factory)) return false;
271   }
272 
273 #ifdef DEBUG
274   if (info->isolate()->bootstrapper()->IsActive()
275           ? FLAG_print_builtin_scopes
276           : FLAG_print_scopes) {
277     scope->Print();
278   }
279 
280   if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
281     PrintF("global : ");
282     top->interface()->Print();
283   }
284 #endif
285 
286   info->PrepareForCompilation(scope);
287   return true;
288 }
289 
290 
Initialize()291 void Scope::Initialize() {
292   ASSERT(!already_resolved());
293 
294   // Add this scope as a new inner scope of the outer scope.
295   if (outer_scope_ != NULL) {
296     outer_scope_->inner_scopes_.Add(this, zone());
297     scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
298   } else {
299     scope_inside_with_ = is_with_scope();
300   }
301 
302   // Declare convenience variables.
303   // Declare and allocate receiver (even for the global scope, and even
304   // if naccesses_ == 0).
305   // NOTE: When loading parameters in the global scope, we must take
306   // care not to access them as properties of the global object, but
307   // instead load them directly from the stack. Currently, the only
308   // such parameter is 'this' which is passed on the stack when
309   // invoking scripts
310   if (is_declaration_scope()) {
311     Variable* var =
312         variables_.Declare(this,
313                            isolate_->factory()->this_string(),
314                            VAR,
315                            false,
316                            Variable::THIS,
317                            kCreatedInitialized);
318     var->AllocateTo(Variable::PARAMETER, -1);
319     receiver_ = var;
320   } else {
321     ASSERT(outer_scope() != NULL);
322     receiver_ = outer_scope()->receiver();
323   }
324 
325   if (is_function_scope()) {
326     // Declare 'arguments' variable which exists in all functions.
327     // Note that it might never be accessed, in which case it won't be
328     // allocated during variable allocation.
329     variables_.Declare(this,
330                        isolate_->factory()->arguments_string(),
331                        VAR,
332                        true,
333                        Variable::ARGUMENTS,
334                        kCreatedInitialized);
335   }
336 }
337 
338 
FinalizeBlockScope()339 Scope* Scope::FinalizeBlockScope() {
340   ASSERT(is_block_scope());
341   ASSERT(internals_.is_empty());
342   ASSERT(temps_.is_empty());
343   ASSERT(params_.is_empty());
344 
345   if (num_var_or_const() > 0) return this;
346 
347   // Remove this scope from outer scope.
348   for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
349     if (outer_scope_->inner_scopes_[i] == this) {
350       outer_scope_->inner_scopes_.Remove(i);
351       break;
352     }
353   }
354 
355   // Reparent inner scopes.
356   for (int i = 0; i < inner_scopes_.length(); i++) {
357     outer_scope()->AddInnerScope(inner_scopes_[i]);
358   }
359 
360   // Move unresolved variables
361   for (int i = 0; i < unresolved_.length(); i++) {
362     outer_scope()->unresolved_.Add(unresolved_[i], zone());
363   }
364 
365   return NULL;
366 }
367 
368 
LookupLocal(Handle<String> name)369 Variable* Scope::LookupLocal(Handle<String> name) {
370   Variable* result = variables_.Lookup(name);
371   if (result != NULL || scope_info_.is_null()) {
372     return result;
373   }
374   // If we have a serialized scope info, we might find the variable there.
375   // There should be no local slot with the given name.
376   ASSERT(scope_info_->StackSlotIndex(*name) < 0);
377 
378   // Check context slot lookup.
379   VariableMode mode;
380   Variable::Location location = Variable::CONTEXT;
381   InitializationFlag init_flag;
382   int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag);
383   if (index < 0) {
384     // Check parameters.
385     index = scope_info_->ParameterIndex(*name);
386     if (index < 0) return NULL;
387 
388     mode = DYNAMIC;
389     location = Variable::LOOKUP;
390     init_flag = kCreatedInitialized;
391   }
392 
393   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
394                                      init_flag);
395   var->AllocateTo(location, index);
396   return var;
397 }
398 
399 
LookupFunctionVar(Handle<String> name,AstNodeFactory<AstNullVisitor> * factory)400 Variable* Scope::LookupFunctionVar(Handle<String> name,
401                                    AstNodeFactory<AstNullVisitor>* factory) {
402   if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
403     return function_->proxy()->var();
404   } else if (!scope_info_.is_null()) {
405     // If we are backed by a scope info, try to lookup the variable there.
406     VariableMode mode;
407     int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
408     if (index < 0) return NULL;
409     Variable* var = new(zone()) Variable(
410         this, name, mode, true /* is valid LHS */,
411         Variable::NORMAL, kCreatedInitialized);
412     VariableProxy* proxy = factory->NewVariableProxy(var);
413     VariableDeclaration* declaration = factory->NewVariableDeclaration(
414         proxy, mode, this, RelocInfo::kNoPosition);
415     DeclareFunctionVar(declaration);
416     var->AllocateTo(Variable::CONTEXT, index);
417     return var;
418   } else {
419     return NULL;
420   }
421 }
422 
423 
Lookup(Handle<String> name)424 Variable* Scope::Lookup(Handle<String> name) {
425   for (Scope* scope = this;
426        scope != NULL;
427        scope = scope->outer_scope()) {
428     Variable* var = scope->LookupLocal(name);
429     if (var != NULL) return var;
430   }
431   return NULL;
432 }
433 
434 
DeclareParameter(Handle<String> name,VariableMode mode)435 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
436   ASSERT(!already_resolved());
437   ASSERT(is_function_scope());
438   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
439                                      kCreatedInitialized);
440   params_.Add(var, zone());
441 }
442 
443 
DeclareLocal(Handle<String> name,VariableMode mode,InitializationFlag init_flag,Interface * interface)444 Variable* Scope::DeclareLocal(Handle<String> name,
445                               VariableMode mode,
446                               InitializationFlag init_flag,
447                               Interface* interface) {
448   ASSERT(!already_resolved());
449   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are
450   // introduces during variable allocation, INTERNAL variables are allocated
451   // explicitly, and TEMPORARY variables are allocated via NewTemporary().
452   ASSERT(IsDeclaredVariableMode(mode));
453   ++num_var_or_const_;
454   return variables_.Declare(
455       this, name, mode, true, Variable::NORMAL, init_flag, interface);
456 }
457 
458 
DeclareDynamicGlobal(Handle<String> name)459 Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
460   ASSERT(is_global_scope());
461   return variables_.Declare(this,
462                             name,
463                             DYNAMIC_GLOBAL,
464                             true,
465                             Variable::NORMAL,
466                             kCreatedInitialized);
467 }
468 
469 
RemoveUnresolved(VariableProxy * var)470 void Scope::RemoveUnresolved(VariableProxy* var) {
471   // Most likely (always?) any variable we want to remove
472   // was just added before, so we search backwards.
473   for (int i = unresolved_.length(); i-- > 0;) {
474     if (unresolved_[i] == var) {
475       unresolved_.Remove(i);
476       return;
477     }
478   }
479 }
480 
481 
NewInternal(Handle<String> name)482 Variable* Scope::NewInternal(Handle<String> name) {
483   ASSERT(!already_resolved());
484   Variable* var = new(zone()) Variable(this,
485                                        name,
486                                        INTERNAL,
487                                        false,
488                                        Variable::NORMAL,
489                                        kCreatedInitialized);
490   internals_.Add(var, zone());
491   return var;
492 }
493 
494 
NewTemporary(Handle<String> name)495 Variable* Scope::NewTemporary(Handle<String> name) {
496   ASSERT(!already_resolved());
497   Variable* var = new(zone()) Variable(this,
498                                        name,
499                                        TEMPORARY,
500                                        true,
501                                        Variable::NORMAL,
502                                        kCreatedInitialized);
503   temps_.Add(var, zone());
504   return var;
505 }
506 
507 
AddDeclaration(Declaration * declaration)508 void Scope::AddDeclaration(Declaration* declaration) {
509   decls_.Add(declaration, zone());
510 }
511 
512 
SetIllegalRedeclaration(Expression * expression)513 void Scope::SetIllegalRedeclaration(Expression* expression) {
514   // Record only the first illegal redeclaration.
515   if (!HasIllegalRedeclaration()) {
516     illegal_redecl_ = expression;
517   }
518   ASSERT(HasIllegalRedeclaration());
519 }
520 
521 
VisitIllegalRedeclaration(AstVisitor * visitor)522 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
523   ASSERT(HasIllegalRedeclaration());
524   illegal_redecl_->Accept(visitor);
525 }
526 
527 
CheckConflictingVarDeclarations()528 Declaration* Scope::CheckConflictingVarDeclarations() {
529   int length = decls_.length();
530   for (int i = 0; i < length; i++) {
531     Declaration* decl = decls_[i];
532     if (decl->mode() != VAR) continue;
533     Handle<String> name = decl->proxy()->name();
534 
535     // Iterate through all scopes until and including the declaration scope.
536     Scope* previous = NULL;
537     Scope* current = decl->scope();
538     do {
539       // There is a conflict if there exists a non-VAR binding.
540       Variable* other_var = current->variables_.Lookup(name);
541       if (other_var != NULL && other_var->mode() != VAR) {
542         return decl;
543       }
544       previous = current;
545       current = current->outer_scope_;
546     } while (!previous->is_declaration_scope());
547   }
548   return NULL;
549 }
550 
551 
552 class VarAndOrder {
553  public:
VarAndOrder(Variable * var,int order)554   VarAndOrder(Variable* var, int order) : var_(var), order_(order) { }
var() const555   Variable* var() const { return var_; }
order() const556   int order() const { return order_; }
Compare(const VarAndOrder * a,const VarAndOrder * b)557   static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
558     return a->order_ - b->order_;
559   }
560 
561  private:
562   Variable* var_;
563   int order_;
564 };
565 
566 
CollectStackAndContextLocals(ZoneList<Variable * > * stack_locals,ZoneList<Variable * > * context_locals)567 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
568                                          ZoneList<Variable*>* context_locals) {
569   ASSERT(stack_locals != NULL);
570   ASSERT(context_locals != NULL);
571 
572   // Collect internals which are always allocated on the heap.
573   for (int i = 0; i < internals_.length(); i++) {
574     Variable* var = internals_[i];
575     if (var->is_used()) {
576       ASSERT(var->IsContextSlot());
577       context_locals->Add(var, zone());
578     }
579   }
580 
581   // Collect temporaries which are always allocated on the stack, unless the
582   // context as a whole has forced context allocation.
583   for (int i = 0; i < temps_.length(); i++) {
584     Variable* var = temps_[i];
585     if (var->is_used()) {
586       if (var->IsContextSlot()) {
587         ASSERT(has_forced_context_allocation());
588         context_locals->Add(var, zone());
589       } else {
590         ASSERT(var->IsStackLocal());
591         stack_locals->Add(var, zone());
592       }
593     }
594   }
595 
596   // Collect declared local variables.
597   ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
598   for (VariableMap::Entry* p = variables_.Start();
599        p != NULL;
600        p = variables_.Next(p)) {
601     Variable* var = reinterpret_cast<Variable*>(p->value);
602     if (var->is_used()) {
603       vars.Add(VarAndOrder(var, p->order), zone());
604     }
605   }
606   vars.Sort(VarAndOrder::Compare);
607   int var_count = vars.length();
608   for (int i = 0; i < var_count; i++) {
609     Variable* var = vars[i].var();
610     if (var->IsStackLocal()) {
611       stack_locals->Add(var, zone());
612     } else if (var->IsContextSlot()) {
613       context_locals->Add(var, zone());
614     }
615   }
616 }
617 
618 
AllocateVariables(CompilationInfo * info,AstNodeFactory<AstNullVisitor> * factory)619 bool Scope::AllocateVariables(CompilationInfo* info,
620                               AstNodeFactory<AstNullVisitor>* factory) {
621   // 1) Propagate scope information.
622   bool outer_scope_calls_sloppy_eval = false;
623   if (outer_scope_ != NULL) {
624     outer_scope_calls_sloppy_eval =
625         outer_scope_->outer_scope_calls_sloppy_eval() |
626         outer_scope_->calls_sloppy_eval();
627   }
628   PropagateScopeInfo(outer_scope_calls_sloppy_eval);
629 
630   // 2) Allocate module instances.
631   if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
632     ASSERT(num_modules_ == 0);
633     AllocateModulesRecursively(this);
634   }
635 
636   // 3) Resolve variables.
637   if (!ResolveVariablesRecursively(info, factory)) return false;
638 
639   // 4) Allocate variables.
640   AllocateVariablesRecursively();
641 
642   return true;
643 }
644 
645 
HasTrivialContext() const646 bool Scope::HasTrivialContext() const {
647   // A function scope has a trivial context if it always is the global
648   // context. We iteratively scan out the context chain to see if
649   // there is anything that makes this scope non-trivial; otherwise we
650   // return true.
651   for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
652     if (scope->is_eval_scope()) return false;
653     if (scope->scope_inside_with_) return false;
654     if (scope->num_heap_slots_ > 0) return false;
655   }
656   return true;
657 }
658 
659 
HasTrivialOuterContext() const660 bool Scope::HasTrivialOuterContext() const {
661   Scope* outer = outer_scope_;
662   if (outer == NULL) return true;
663   // Note that the outer context may be trivial in general, but the current
664   // scope may be inside a 'with' statement in which case the outer context
665   // for this scope is not trivial.
666   return !scope_inside_with_ && outer->HasTrivialContext();
667 }
668 
669 
HasLazyCompilableOuterContext() const670 bool Scope::HasLazyCompilableOuterContext() const {
671   Scope* outer = outer_scope_;
672   if (outer == NULL) return true;
673   // We have to prevent lazy compilation if this scope is inside a with scope
674   // and all declaration scopes between them have empty contexts. Such
675   // declaration scopes may become invisible during scope info deserialization.
676   outer = outer->DeclarationScope();
677   bool found_non_trivial_declarations = false;
678   for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) {
679     if (scope->is_with_scope() && !found_non_trivial_declarations) return false;
680     if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) {
681       found_non_trivial_declarations = true;
682     }
683   }
684   return true;
685 }
686 
687 
AllowsLazyCompilation() const688 bool Scope::AllowsLazyCompilation() const {
689   return !force_eager_compilation_ && HasLazyCompilableOuterContext();
690 }
691 
692 
AllowsLazyCompilationWithoutContext() const693 bool Scope::AllowsLazyCompilationWithoutContext() const {
694   return !force_eager_compilation_ && HasTrivialOuterContext();
695 }
696 
697 
ContextChainLength(Scope * scope)698 int Scope::ContextChainLength(Scope* scope) {
699   int n = 0;
700   for (Scope* s = this; s != scope; s = s->outer_scope_) {
701     ASSERT(s != NULL);  // scope must be in the scope chain
702     if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
703     // Catch and module scopes always have heap slots.
704     ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0);
705     ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0);
706   }
707   return n;
708 }
709 
710 
GlobalScope()711 Scope* Scope::GlobalScope() {
712   Scope* scope = this;
713   while (!scope->is_global_scope()) {
714     scope = scope->outer_scope();
715   }
716   return scope;
717 }
718 
719 
DeclarationScope()720 Scope* Scope::DeclarationScope() {
721   Scope* scope = this;
722   while (!scope->is_declaration_scope()) {
723     scope = scope->outer_scope();
724   }
725   return scope;
726 }
727 
728 
GetScopeInfo()729 Handle<ScopeInfo> Scope::GetScopeInfo() {
730   if (scope_info_.is_null()) {
731     scope_info_ = ScopeInfo::Create(this, zone());
732   }
733   return scope_info_;
734 }
735 
736 
GetNestedScopeChain(List<Handle<ScopeInfo>> * chain,int position)737 void Scope::GetNestedScopeChain(
738     List<Handle<ScopeInfo> >* chain,
739     int position) {
740   if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
741 
742   for (int i = 0; i < inner_scopes_.length(); i++) {
743     Scope* scope = inner_scopes_[i];
744     int beg_pos = scope->start_position();
745     int end_pos = scope->end_position();
746     ASSERT(beg_pos >= 0 && end_pos >= 0);
747     if (beg_pos <= position && position < end_pos) {
748       scope->GetNestedScopeChain(chain, position);
749       return;
750     }
751   }
752 }
753 
754 
755 #ifdef DEBUG
Header(ScopeType scope_type)756 static const char* Header(ScopeType scope_type) {
757   switch (scope_type) {
758     case EVAL_SCOPE: return "eval";
759     case FUNCTION_SCOPE: return "function";
760     case MODULE_SCOPE: return "module";
761     case GLOBAL_SCOPE: return "global";
762     case CATCH_SCOPE: return "catch";
763     case BLOCK_SCOPE: return "block";
764     case WITH_SCOPE: return "with";
765   }
766   UNREACHABLE();
767   return NULL;
768 }
769 
770 
Indent(int n,const char * str)771 static void Indent(int n, const char* str) {
772   PrintF("%*s%s", n, "", str);
773 }
774 
775 
PrintName(Handle<String> name)776 static void PrintName(Handle<String> name) {
777   SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
778   PrintF("%s", s.get());
779 }
780 
781 
PrintLocation(Variable * var)782 static void PrintLocation(Variable* var) {
783   switch (var->location()) {
784     case Variable::UNALLOCATED:
785       break;
786     case Variable::PARAMETER:
787       PrintF("parameter[%d]", var->index());
788       break;
789     case Variable::LOCAL:
790       PrintF("local[%d]", var->index());
791       break;
792     case Variable::CONTEXT:
793       PrintF("context[%d]", var->index());
794       break;
795     case Variable::LOOKUP:
796       PrintF("lookup");
797       break;
798   }
799 }
800 
801 
PrintVar(int indent,Variable * var)802 static void PrintVar(int indent, Variable* var) {
803   if (var->is_used() || !var->IsUnallocated()) {
804     Indent(indent, Variable::Mode2String(var->mode()));
805     PrintF(" ");
806     PrintName(var->name());
807     PrintF(";  // ");
808     PrintLocation(var);
809     if (var->has_forced_context_allocation()) {
810       if (!var->IsUnallocated()) PrintF(", ");
811       PrintF("forced context allocation");
812     }
813     PrintF("\n");
814   }
815 }
816 
817 
PrintMap(int indent,VariableMap * map)818 static void PrintMap(int indent, VariableMap* map) {
819   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
820     Variable* var = reinterpret_cast<Variable*>(p->value);
821     PrintVar(indent, var);
822   }
823 }
824 
825 
Print(int n)826 void Scope::Print(int n) {
827   int n0 = (n > 0 ? n : 0);
828   int n1 = n0 + 2;  // indentation
829 
830   // Print header.
831   Indent(n0, Header(scope_type_));
832   if (scope_name_->length() > 0) {
833     PrintF(" ");
834     PrintName(scope_name_);
835   }
836 
837   // Print parameters, if any.
838   if (is_function_scope()) {
839     PrintF(" (");
840     for (int i = 0; i < params_.length(); i++) {
841       if (i > 0) PrintF(", ");
842       PrintName(params_[i]->name());
843     }
844     PrintF(")");
845   }
846 
847   PrintF(" { // (%d, %d)\n", start_position(), end_position());
848 
849   // Function name, if any (named function literals, only).
850   if (function_ != NULL) {
851     Indent(n1, "// (local) function name: ");
852     PrintName(function_->proxy()->name());
853     PrintF("\n");
854   }
855 
856   // Scope info.
857   if (HasTrivialOuterContext()) {
858     Indent(n1, "// scope has trivial outer context\n");
859   }
860   if (strict_mode() == STRICT) {
861     Indent(n1, "// strict mode scope\n");
862   }
863   if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
864   if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
865   if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
866   if (outer_scope_calls_sloppy_eval_) {
867     Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
868   }
869   if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
870   if (num_stack_slots_ > 0) { Indent(n1, "// ");
871   PrintF("%d stack slots\n", num_stack_slots_); }
872   if (num_heap_slots_ > 0) { Indent(n1, "// ");
873   PrintF("%d heap slots\n", num_heap_slots_); }
874 
875   // Print locals.
876   if (function_ != NULL) {
877     Indent(n1, "// function var:\n");
878     PrintVar(n1, function_->proxy()->var());
879   }
880 
881   if (temps_.length() > 0) {
882     Indent(n1, "// temporary vars:\n");
883     for (int i = 0; i < temps_.length(); i++) {
884       PrintVar(n1, temps_[i]);
885     }
886   }
887 
888   if (internals_.length() > 0) {
889     Indent(n1, "// internal vars:\n");
890     for (int i = 0; i < internals_.length(); i++) {
891       PrintVar(n1, internals_[i]);
892     }
893   }
894 
895   if (variables_.Start() != NULL) {
896     Indent(n1, "// local vars:\n");
897     PrintMap(n1, &variables_);
898   }
899 
900   if (dynamics_ != NULL) {
901     Indent(n1, "// dynamic vars:\n");
902     PrintMap(n1, dynamics_->GetMap(DYNAMIC));
903     PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
904     PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
905   }
906 
907   // Print inner scopes (disable by providing negative n).
908   if (n >= 0) {
909     for (int i = 0; i < inner_scopes_.length(); i++) {
910       PrintF("\n");
911       inner_scopes_[i]->Print(n1);
912     }
913   }
914 
915   Indent(n0, "}\n");
916 }
917 #endif  // DEBUG
918 
919 
NonLocal(Handle<String> name,VariableMode mode)920 Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
921   if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
922   VariableMap* map = dynamics_->GetMap(mode);
923   Variable* var = map->Lookup(name);
924   if (var == NULL) {
925     // Declare a new non-local.
926     InitializationFlag init_flag = (mode == VAR)
927         ? kCreatedInitialized : kNeedsInitialization;
928     var = map->Declare(NULL,
929                        name,
930                        mode,
931                        true,
932                        Variable::NORMAL,
933                        init_flag);
934     // Allocate it by giving it a dynamic lookup.
935     var->AllocateTo(Variable::LOOKUP, -1);
936   }
937   return var;
938 }
939 
940 
LookupRecursive(Handle<String> name,BindingKind * binding_kind,AstNodeFactory<AstNullVisitor> * factory)941 Variable* Scope::LookupRecursive(Handle<String> name,
942                                  BindingKind* binding_kind,
943                                  AstNodeFactory<AstNullVisitor>* factory) {
944   ASSERT(binding_kind != NULL);
945   if (already_resolved() && is_with_scope()) {
946     // Short-cut: if the scope is deserialized from a scope info, variable
947     // allocation is already fixed.  We can simply return with dynamic lookup.
948     *binding_kind = DYNAMIC_LOOKUP;
949     return NULL;
950   }
951 
952   // Try to find the variable in this scope.
953   Variable* var = LookupLocal(name);
954 
955   // We found a variable and we are done. (Even if there is an 'eval' in
956   // this scope which introduces the same variable again, the resulting
957   // variable remains the same.)
958   if (var != NULL) {
959     *binding_kind = BOUND;
960     return var;
961   }
962 
963   // We did not find a variable locally. Check against the function variable,
964   // if any. We can do this for all scopes, since the function variable is
965   // only present - if at all - for function scopes.
966   *binding_kind = UNBOUND;
967   var = LookupFunctionVar(name, factory);
968   if (var != NULL) {
969     *binding_kind = BOUND;
970   } else if (outer_scope_ != NULL) {
971     var = outer_scope_->LookupRecursive(name, binding_kind, factory);
972     if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
973       var->ForceContextAllocation();
974     }
975   } else {
976     ASSERT(is_global_scope());
977   }
978 
979   if (is_with_scope()) {
980     ASSERT(!already_resolved());
981     // The current scope is a with scope, so the variable binding can not be
982     // statically resolved. However, note that it was necessary to do a lookup
983     // in the outer scope anyway, because if a binding exists in an outer scope,
984     // the associated variable has to be marked as potentially being accessed
985     // from inside of an inner with scope (the property may not be in the 'with'
986     // object).
987     *binding_kind = DYNAMIC_LOOKUP;
988     return NULL;
989   } else if (calls_sloppy_eval()) {
990     // A variable binding may have been found in an outer scope, but the current
991     // scope makes a sloppy 'eval' call, so the found variable may not be
992     // the correct one (the 'eval' may introduce a binding with the same name).
993     // In that case, change the lookup result to reflect this situation.
994     if (*binding_kind == BOUND) {
995       *binding_kind = BOUND_EVAL_SHADOWED;
996     } else if (*binding_kind == UNBOUND) {
997       *binding_kind = UNBOUND_EVAL_SHADOWED;
998     }
999   }
1000   return var;
1001 }
1002 
1003 
ResolveVariable(CompilationInfo * info,VariableProxy * proxy,AstNodeFactory<AstNullVisitor> * factory)1004 bool Scope::ResolveVariable(CompilationInfo* info,
1005                             VariableProxy* proxy,
1006                             AstNodeFactory<AstNullVisitor>* factory) {
1007   ASSERT(info->global_scope()->is_global_scope());
1008 
1009   // If the proxy is already resolved there's nothing to do
1010   // (functions and consts may be resolved by the parser).
1011   if (proxy->var() != NULL) return true;
1012 
1013   // Otherwise, try to resolve the variable.
1014   BindingKind binding_kind;
1015   Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
1016   switch (binding_kind) {
1017     case BOUND:
1018       // We found a variable binding.
1019       break;
1020 
1021     case BOUND_EVAL_SHADOWED:
1022       // We either found a variable binding that might be shadowed by eval  or
1023       // gave up on it (e.g. by encountering a local with the same in the outer
1024       // scope which was not promoted to a context, this can happen if we use
1025       // debugger to evaluate arbitrary expressions at a break point).
1026       if (var->IsGlobalObjectProperty()) {
1027         var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
1028       } else if (var->is_dynamic()) {
1029         var = NonLocal(proxy->name(), DYNAMIC);
1030       } else {
1031         Variable* invalidated = var;
1032         var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
1033         var->set_local_if_not_shadowed(invalidated);
1034       }
1035       break;
1036 
1037     case UNBOUND:
1038       // No binding has been found. Declare a variable on the global object.
1039       var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
1040       break;
1041 
1042     case UNBOUND_EVAL_SHADOWED:
1043       // No binding has been found. But some scope makes a sloppy 'eval' call.
1044       var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
1045       break;
1046 
1047     case DYNAMIC_LOOKUP:
1048       // The variable could not be resolved statically.
1049       var = NonLocal(proxy->name(), DYNAMIC);
1050       break;
1051   }
1052 
1053   ASSERT(var != NULL);
1054 
1055   if (FLAG_harmony_scoping && strict_mode() == STRICT &&
1056       var->is_const_mode() && proxy->IsLValue()) {
1057     // Assignment to const. Throw a syntax error.
1058     MessageLocation location(
1059         info->script(), proxy->position(), proxy->position());
1060     Isolate* isolate = info->isolate();
1061     Factory* factory = isolate->factory();
1062     Handle<JSArray> array = factory->NewJSArray(0);
1063     Handle<Object> result =
1064         factory->NewSyntaxError("harmony_const_assign", array);
1065     isolate->Throw(*result, &location);
1066     return false;
1067   }
1068 
1069   if (FLAG_harmony_modules) {
1070     bool ok;
1071 #ifdef DEBUG
1072     if (FLAG_print_interface_details)
1073       PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
1074 #endif
1075     proxy->interface()->Unify(var->interface(), zone(), &ok);
1076     if (!ok) {
1077 #ifdef DEBUG
1078       if (FLAG_print_interfaces) {
1079         PrintF("SCOPES TYPE ERROR\n");
1080         PrintF("proxy: ");
1081         proxy->interface()->Print();
1082         PrintF("var: ");
1083         var->interface()->Print();
1084       }
1085 #endif
1086 
1087       // Inconsistent use of module. Throw a syntax error.
1088       // TODO(rossberg): generate more helpful error message.
1089       MessageLocation location(
1090           info->script(), proxy->position(), proxy->position());
1091       Isolate* isolate = info->isolate();
1092       Factory* factory = isolate->factory();
1093       Handle<JSArray> array = factory->NewJSArray(1);
1094       JSObject::SetElement(array, 0, var->name(), NONE, STRICT).Assert();
1095       Handle<Object> result =
1096           factory->NewSyntaxError("module_type_error", array);
1097       isolate->Throw(*result, &location);
1098       return false;
1099     }
1100   }
1101 
1102   proxy->BindTo(var);
1103 
1104   return true;
1105 }
1106 
1107 
ResolveVariablesRecursively(CompilationInfo * info,AstNodeFactory<AstNullVisitor> * factory)1108 bool Scope::ResolveVariablesRecursively(
1109     CompilationInfo* info,
1110     AstNodeFactory<AstNullVisitor>* factory) {
1111   ASSERT(info->global_scope()->is_global_scope());
1112 
1113   // Resolve unresolved variables for this scope.
1114   for (int i = 0; i < unresolved_.length(); i++) {
1115     if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1116   }
1117 
1118   // Resolve unresolved variables for inner scopes.
1119   for (int i = 0; i < inner_scopes_.length(); i++) {
1120     if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1121       return false;
1122   }
1123 
1124   return true;
1125 }
1126 
1127 
PropagateScopeInfo(bool outer_scope_calls_sloppy_eval)1128 bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
1129   if (outer_scope_calls_sloppy_eval) {
1130     outer_scope_calls_sloppy_eval_ = true;
1131   }
1132 
1133   bool calls_sloppy_eval =
1134       this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
1135   for (int i = 0; i < inner_scopes_.length(); i++) {
1136     Scope* inner_scope = inner_scopes_[i];
1137     if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) {
1138       inner_scope_calls_eval_ = true;
1139     }
1140     if (inner_scope->force_eager_compilation_) {
1141       force_eager_compilation_ = true;
1142     }
1143   }
1144 
1145   return scope_calls_eval_ || inner_scope_calls_eval_;
1146 }
1147 
1148 
MustAllocate(Variable * var)1149 bool Scope::MustAllocate(Variable* var) {
1150   // Give var a read/write use if there is a chance it might be accessed
1151   // via an eval() call.  This is only possible if the variable has a
1152   // visible name.
1153   if ((var->is_this() || var->name()->length() > 0) &&
1154       (var->has_forced_context_allocation() ||
1155        scope_calls_eval_ ||
1156        inner_scope_calls_eval_ ||
1157        scope_contains_with_ ||
1158        is_catch_scope() ||
1159        is_block_scope() ||
1160        is_module_scope() ||
1161        is_global_scope())) {
1162     var->set_is_used(true);
1163   }
1164   // Global variables do not need to be allocated.
1165   return !var->IsGlobalObjectProperty() && var->is_used();
1166 }
1167 
1168 
MustAllocateInContext(Variable * var)1169 bool Scope::MustAllocateInContext(Variable* var) {
1170   // If var is accessed from an inner scope, or if there is a possibility
1171   // that it might be accessed from the current or an inner scope (through
1172   // an eval() call or a runtime with lookup), it must be allocated in the
1173   // context.
1174   //
1175   // Exceptions: If the scope as a whole has forced context allocation, all
1176   // variables will have context allocation, even temporaries.  Otherwise
1177   // temporary variables are always stack-allocated.  Catch-bound variables are
1178   // always context-allocated.
1179   if (has_forced_context_allocation()) return true;
1180   if (var->mode() == TEMPORARY) return false;
1181   if (var->mode() == INTERNAL) return true;
1182   if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
1183   if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true;
1184   return var->has_forced_context_allocation() ||
1185       scope_calls_eval_ ||
1186       inner_scope_calls_eval_ ||
1187       scope_contains_with_;
1188 }
1189 
1190 
HasArgumentsParameter()1191 bool Scope::HasArgumentsParameter() {
1192   for (int i = 0; i < params_.length(); i++) {
1193     if (params_[i]->name().is_identical_to(
1194             isolate_->factory()->arguments_string())) {
1195       return true;
1196     }
1197   }
1198   return false;
1199 }
1200 
1201 
AllocateStackSlot(Variable * var)1202 void Scope::AllocateStackSlot(Variable* var) {
1203   var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
1204 }
1205 
1206 
AllocateHeapSlot(Variable * var)1207 void Scope::AllocateHeapSlot(Variable* var) {
1208   var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
1209 }
1210 
1211 
AllocateParameterLocals()1212 void Scope::AllocateParameterLocals() {
1213   ASSERT(is_function_scope());
1214   Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
1215   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
1216 
1217   bool uses_sloppy_arguments = false;
1218 
1219   if (MustAllocate(arguments) && !HasArgumentsParameter()) {
1220     // 'arguments' is used. Unless there is also a parameter called
1221     // 'arguments', we must be conservative and allocate all parameters to
1222     // the context assuming they will be captured by the arguments object.
1223     // If we have a parameter named 'arguments', a (new) value is always
1224     // assigned to it via the function invocation. Then 'arguments' denotes
1225     // that specific parameter value and cannot be used to access the
1226     // parameters, which is why we don't need to allocate an arguments
1227     // object in that case.
1228 
1229     // We are using 'arguments'. Tell the code generator that is needs to
1230     // allocate the arguments object by setting 'arguments_'.
1231     arguments_ = arguments;
1232 
1233     // In strict mode 'arguments' does not alias formal parameters.
1234     // Therefore in strict mode we allocate parameters as if 'arguments'
1235     // were not used.
1236     uses_sloppy_arguments = strict_mode() == SLOPPY;
1237   }
1238 
1239   // The same parameter may occur multiple times in the parameters_ list.
1240   // If it does, and if it is not copied into the context object, it must
1241   // receive the highest parameter index for that parameter; thus iteration
1242   // order is relevant!
1243   for (int i = params_.length() - 1; i >= 0; --i) {
1244     Variable* var = params_[i];
1245     ASSERT(var->scope() == this);
1246     if (uses_sloppy_arguments || has_forced_context_allocation()) {
1247       // Force context allocation of the parameter.
1248       var->ForceContextAllocation();
1249     }
1250 
1251     if (MustAllocate(var)) {
1252       if (MustAllocateInContext(var)) {
1253         ASSERT(var->IsUnallocated() || var->IsContextSlot());
1254         if (var->IsUnallocated()) {
1255           AllocateHeapSlot(var);
1256         }
1257       } else {
1258         ASSERT(var->IsUnallocated() || var->IsParameter());
1259         if (var->IsUnallocated()) {
1260           var->AllocateTo(Variable::PARAMETER, i);
1261         }
1262       }
1263     }
1264   }
1265 }
1266 
1267 
AllocateNonParameterLocal(Variable * var)1268 void Scope::AllocateNonParameterLocal(Variable* var) {
1269   ASSERT(var->scope() == this);
1270   ASSERT(!var->IsVariable(isolate_->factory()->dot_result_string()) ||
1271          !var->IsStackLocal());
1272   if (var->IsUnallocated() && MustAllocate(var)) {
1273     if (MustAllocateInContext(var)) {
1274       AllocateHeapSlot(var);
1275     } else {
1276       AllocateStackSlot(var);
1277     }
1278   }
1279 }
1280 
1281 
AllocateNonParameterLocals()1282 void Scope::AllocateNonParameterLocals() {
1283   // All variables that have no rewrite yet are non-parameter locals.
1284   for (int i = 0; i < temps_.length(); i++) {
1285     AllocateNonParameterLocal(temps_[i]);
1286   }
1287 
1288   for (int i = 0; i < internals_.length(); i++) {
1289     AllocateNonParameterLocal(internals_[i]);
1290   }
1291 
1292   ZoneList<VarAndOrder> vars(variables_.occupancy(), zone());
1293   for (VariableMap::Entry* p = variables_.Start();
1294        p != NULL;
1295        p = variables_.Next(p)) {
1296     Variable* var = reinterpret_cast<Variable*>(p->value);
1297     vars.Add(VarAndOrder(var, p->order), zone());
1298   }
1299   vars.Sort(VarAndOrder::Compare);
1300   int var_count = vars.length();
1301   for (int i = 0; i < var_count; i++) {
1302     AllocateNonParameterLocal(vars[i].var());
1303   }
1304 
1305   // For now, function_ must be allocated at the very end.  If it gets
1306   // allocated in the context, it must be the last slot in the context,
1307   // because of the current ScopeInfo implementation (see
1308   // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1309   if (function_ != NULL) {
1310     AllocateNonParameterLocal(function_->proxy()->var());
1311   }
1312 }
1313 
1314 
AllocateVariablesRecursively()1315 void Scope::AllocateVariablesRecursively() {
1316   // Allocate variables for inner scopes.
1317   for (int i = 0; i < inner_scopes_.length(); i++) {
1318     inner_scopes_[i]->AllocateVariablesRecursively();
1319   }
1320 
1321   // If scope is already resolved, we still need to allocate
1322   // variables in inner scopes which might not had been resolved yet.
1323   if (already_resolved()) return;
1324   // The number of slots required for variables.
1325   num_stack_slots_ = 0;
1326   num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1327 
1328   // Allocate variables for this scope.
1329   // Parameters must be allocated first, if any.
1330   if (is_function_scope()) AllocateParameterLocals();
1331   AllocateNonParameterLocals();
1332 
1333   // Force allocation of a context for this scope if necessary. For a 'with'
1334   // scope and for a function scope that makes an 'eval' call we need a context,
1335   // even if no local variables were statically allocated in the scope.
1336   // Likewise for modules.
1337   bool must_have_context = is_with_scope() || is_module_scope() ||
1338       (is_function_scope() && calls_eval());
1339 
1340   // If we didn't allocate any locals in the local context, then we only
1341   // need the minimal number of slots if we must have a context.
1342   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1343     num_heap_slots_ = 0;
1344   }
1345 
1346   // Allocation done.
1347   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1348 }
1349 
1350 
AllocateModulesRecursively(Scope * host_scope)1351 void Scope::AllocateModulesRecursively(Scope* host_scope) {
1352   if (already_resolved()) return;
1353   if (is_module_scope()) {
1354     ASSERT(interface_->IsFrozen());
1355     Handle<String> name = isolate_->factory()->InternalizeOneByteString(
1356         STATIC_ASCII_VECTOR(".module"));
1357     ASSERT(module_var_ == NULL);
1358     module_var_ = host_scope->NewInternal(name);
1359     ++host_scope->num_modules_;
1360   }
1361 
1362   for (int i = 0; i < inner_scopes_.length(); i++) {
1363     Scope* inner_scope = inner_scopes_.at(i);
1364     inner_scope->AllocateModulesRecursively(host_scope);
1365   }
1366 }
1367 
1368 
StackLocalCount() const1369 int Scope::StackLocalCount() const {
1370   return num_stack_slots() -
1371       (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1372 }
1373 
1374 
ContextLocalCount() const1375 int Scope::ContextLocalCount() const {
1376   if (num_heap_slots() == 0) return 0;
1377   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1378       (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1379 }
1380 
1381 } }  // namespace v8::internal
1382