1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "bootstrapper.h"
35 #include "scopeinfo.h"
37 #include "allocation-inl.h"
42 // ----------------------------------------------------------------------------
43 // Implementation of LocalsMap
45 // Note: We are storing the handle locations as key values in the hash map.
46 // When inserting a new variable via Declare(), we rely on the fact that
47 // the handle location remains alive for the duration of that variable
48 // use. Because a Variable holding a handle with the same location exists
51 static bool Match(void* key1, void* key2) {
52 String* name1 = *reinterpret_cast<String**>(key1);
53 String* name2 = *reinterpret_cast<String**>(key2);
54 ASSERT(name1->IsSymbol());
55 ASSERT(name2->IsSymbol());
56 return name1 == name2;
60 VariableMap::VariableMap() : ZoneHashMap(Match, 8) {}
61 VariableMap::~VariableMap() {}
64 Variable* VariableMap::Declare(
70 InitializationFlag initialization_flag,
71 Interface* interface) {
72 Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true);
73 if (p->value == NULL) {
74 // The variable has not been declared yet -> insert it.
75 ASSERT(p->key == name.location());
76 p->value = new Variable(scope,
84 return reinterpret_cast<Variable*>(p->value);
88 Variable* VariableMap::Lookup(Handle<String> name) {
89 Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false);
91 ASSERT(*reinterpret_cast<String**>(p->key) == *name);
92 ASSERT(p->value != NULL);
93 return reinterpret_cast<Variable*>(p->value);
99 // ----------------------------------------------------------------------------
100 // Implementation of Scope
102 Scope::Scope(Scope* outer_scope, ScopeType type)
103 : isolate_(Isolate::Current()),
110 interface_(FLAG_harmony_modules &&
111 (type == MODULE_SCOPE || type == GLOBAL_SCOPE)
112 ? Interface::NewModule() : NULL),
113 already_resolved_(false) {
114 SetDefaults(type, outer_scope, Handle<ScopeInfo>::null());
115 // At some point we might want to provide outer scopes to
116 // eval scopes (by walking the stack and reading the scope info).
117 // In that case, the ASSERT below needs to be adjusted.
118 ASSERT_EQ(type == GLOBAL_SCOPE, outer_scope == NULL);
119 ASSERT(!HasIllegalRedeclaration());
123 Scope::Scope(Scope* inner_scope,
125 Handle<ScopeInfo> scope_info)
126 : isolate_(Isolate::Current()),
134 already_resolved_(true) {
135 SetDefaults(type, NULL, scope_info);
136 if (!scope_info.is_null()) {
137 num_heap_slots_ = scope_info_->ContextLength();
139 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context.
140 num_heap_slots_ = Max(num_heap_slots_,
141 static_cast<int>(Context::MIN_CONTEXT_SLOTS));
142 AddInnerScope(inner_scope);
146 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
147 : isolate_(Isolate::Current()),
155 already_resolved_(true) {
156 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
157 AddInnerScope(inner_scope);
159 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
160 Variable* variable = variables_.Declare(this,
163 true, // Valid left-hand side.
165 kCreatedInitialized);
166 AllocateHeapSlot(variable);
170 void Scope::SetDefaults(ScopeType type,
172 Handle<ScopeInfo> scope_info) {
173 outer_scope_ = outer_scope;
175 scope_name_ = isolate_->factory()->empty_symbol();
180 illegal_redecl_ = NULL;
181 scope_inside_with_ = false;
182 scope_contains_with_ = false;
183 scope_calls_eval_ = false;
184 // Inherit the strict mode from the parent scope.
185 language_mode_ = (outer_scope != NULL)
186 ? outer_scope->language_mode_ : CLASSIC_MODE;
187 outer_scope_calls_non_strict_eval_ = false;
188 inner_scope_calls_eval_ = false;
189 force_eager_compilation_ = false;
190 num_var_or_const_ = 0;
191 num_stack_slots_ = 0;
193 scope_info_ = scope_info;
194 start_position_ = RelocInfo::kNoPosition;
195 end_position_ = RelocInfo::kNoPosition;
196 if (!scope_info.is_null()) {
197 scope_calls_eval_ = scope_info->CallsEval();
198 language_mode_ = scope_info->language_mode();
203 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope) {
204 // Reconstruct the outer scope chain from a closure's context chain.
205 Scope* current_scope = NULL;
206 Scope* innermost_scope = NULL;
207 bool contains_with = false;
208 while (!context->IsGlobalContext()) {
209 if (context->IsWithContext()) {
210 Scope* with_scope = new Scope(current_scope,
212 Handle<ScopeInfo>::null());
213 current_scope = with_scope;
214 // All the inner scopes are inside a with.
215 contains_with = true;
216 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
217 s->scope_inside_with_ = true;
219 } else if (context->IsFunctionContext()) {
220 ScopeInfo* scope_info = context->closure()->shared()->scope_info();
221 current_scope = new Scope(current_scope,
223 Handle<ScopeInfo>(scope_info));
224 } else if (context->IsBlockContext()) {
225 ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
226 current_scope = new Scope(current_scope,
228 Handle<ScopeInfo>(scope_info));
230 ASSERT(context->IsCatchContext());
231 String* name = String::cast(context->extension());
232 current_scope = new Scope(current_scope, Handle<String>(name));
234 if (contains_with) current_scope->RecordWithStatement();
235 if (innermost_scope == NULL) innermost_scope = current_scope;
237 // Forget about a with when we move to a context for a different function.
238 if (context->previous()->closure() != context->closure()) {
239 contains_with = false;
241 context = context->previous();
244 global_scope->AddInnerScope(current_scope);
245 global_scope->PropagateScopeInfo(false);
246 return (innermost_scope == NULL) ? global_scope : innermost_scope;
250 bool Scope::Analyze(CompilationInfo* info) {
251 ASSERT(info->function() != NULL);
252 Scope* scope = info->function()->scope();
255 // Traverse the scope tree up to the first unresolved scope or the global
256 // scope and start scope resolution and variable allocation from that scope.
257 while (!top->is_global_scope() &&
258 !top->outer_scope()->already_resolved()) {
259 top = top->outer_scope();
262 // Allocate the variables.
264 AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate());
265 if (!top->AllocateVariables(info, &ast_node_factory)) return false;
269 if (info->isolate()->bootstrapper()->IsActive()
270 ? FLAG_print_builtin_scopes
271 : FLAG_print_scopes) {
275 if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) {
277 top->interface()->Print();
281 if (FLAG_harmony_scoping) {
282 VariableProxy* proxy = scope->CheckAssignmentToConst();
284 // Found an assignment to const. Throw a syntax error.
285 MessageLocation location(info->script(),
288 Isolate* isolate = info->isolate();
289 Factory* factory = isolate->factory();
290 Handle<JSArray> array = factory->NewJSArray(0);
291 Handle<Object> result =
292 factory->NewSyntaxError("harmony_const_assign", array);
293 isolate->Throw(*result, &location);
298 info->SetScope(scope);
303 void Scope::Initialize() {
304 ASSERT(!already_resolved());
306 // Add this scope as a new inner scope of the outer scope.
307 if (outer_scope_ != NULL) {
308 outer_scope_->inner_scopes_.Add(this);
309 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope();
311 scope_inside_with_ = is_with_scope();
314 // Declare convenience variables.
315 // Declare and allocate receiver (even for the global scope, and even
316 // if naccesses_ == 0).
317 // NOTE: When loading parameters in the global scope, we must take
318 // care not to access them as properties of the global object, but
319 // instead load them directly from the stack. Currently, the only
320 // such parameter is 'this' which is passed on the stack when
322 if (is_declaration_scope()) {
324 variables_.Declare(this,
325 isolate_->factory()->this_symbol(),
329 kCreatedInitialized);
330 var->AllocateTo(Variable::PARAMETER, -1);
333 ASSERT(outer_scope() != NULL);
334 receiver_ = outer_scope()->receiver();
337 if (is_function_scope()) {
338 // Declare 'arguments' variable which exists in all functions.
339 // Note that it might never be accessed, in which case it won't be
340 // allocated during variable allocation.
341 variables_.Declare(this,
342 isolate_->factory()->arguments_symbol(),
346 kCreatedInitialized);
351 Scope* Scope::FinalizeBlockScope() {
352 ASSERT(is_block_scope());
353 ASSERT(temps_.is_empty());
354 ASSERT(params_.is_empty());
356 if (num_var_or_const() > 0) return this;
358 // Remove this scope from outer scope.
359 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
360 if (outer_scope_->inner_scopes_[i] == this) {
361 outer_scope_->inner_scopes_.Remove(i);
366 // Reparent inner scopes.
367 for (int i = 0; i < inner_scopes_.length(); i++) {
368 outer_scope()->AddInnerScope(inner_scopes_[i]);
371 // Move unresolved variables
372 for (int i = 0; i < unresolved_.length(); i++) {
373 outer_scope()->unresolved_.Add(unresolved_[i]);
380 Variable* Scope::LocalLookup(Handle<String> name) {
381 Variable* result = variables_.Lookup(name);
382 if (result != NULL || scope_info_.is_null()) {
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 ASSERT(scope_info_->StackSlotIndex(*name) < 0);
389 // Check context slot lookup.
391 Variable::Location location = Variable::CONTEXT;
392 InitializationFlag init_flag;
393 int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag);
396 index = scope_info_->ParameterIndex(*name);
397 if (index < 0) return NULL;
400 location = Variable::LOOKUP;
401 init_flag = kCreatedInitialized;
405 variables_.Declare(this,
411 var->AllocateTo(location, index);
416 Variable* Scope::LookupFunctionVar(Handle<String> name,
417 AstNodeFactory<AstNullVisitor>* factory) {
418 if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
419 return function_->proxy()->var();
420 } else if (!scope_info_.is_null()) {
421 // If we are backed by a scope info, try to lookup the variable there.
423 int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
424 if (index < 0) return NULL;
425 Variable* var = new Variable(
426 this, name, mode, true /* is valid LHS */,
427 Variable::NORMAL, kCreatedInitialized);
428 VariableProxy* proxy = factory->NewVariableProxy(var);
429 VariableDeclaration* declaration =
430 factory->NewVariableDeclaration(proxy, mode, this);
431 DeclareFunctionVar(declaration);
432 var->AllocateTo(Variable::CONTEXT, index);
440 Variable* Scope::Lookup(Handle<String> name) {
441 for (Scope* scope = this;
443 scope = scope->outer_scope()) {
444 Variable* var = scope->LocalLookup(name);
445 if (var != NULL) return var;
451 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
452 ASSERT(!already_resolved());
453 ASSERT(is_function_scope());
454 Variable* var = variables_.Declare(
455 this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
460 Variable* Scope::DeclareLocal(Handle<String> name,
462 InitializationFlag init_flag,
463 Interface* interface) {
464 ASSERT(!already_resolved());
465 // This function handles VAR and CONST modes. DYNAMIC variables are
466 // introduces during variable allocation, INTERNAL variables are allocated
467 // explicitly, and TEMPORARY variables are allocated via NewTemporary().
468 ASSERT(mode == VAR ||
470 mode == CONST_HARMONY ||
473 return variables_.Declare(
474 this, name, mode, true, Variable::NORMAL, init_flag, interface);
478 Variable* Scope::DeclareGlobal(Handle<String> name) {
479 ASSERT(is_global_scope());
480 return variables_.Declare(this,
485 kCreatedInitialized);
489 void Scope::RemoveUnresolved(VariableProxy* var) {
490 // Most likely (always?) any variable we want to remove
491 // was just added before, so we search backwards.
492 for (int i = unresolved_.length(); i-- > 0;) {
493 if (unresolved_[i] == var) {
494 unresolved_.Remove(i);
501 Variable* Scope::NewTemporary(Handle<String> name) {
502 ASSERT(!already_resolved());
503 Variable* var = new Variable(this,
508 kCreatedInitialized);
514 void Scope::AddDeclaration(Declaration* declaration) {
515 decls_.Add(declaration);
519 void Scope::SetIllegalRedeclaration(Expression* expression) {
520 // Record only the first illegal redeclaration.
521 if (!HasIllegalRedeclaration()) {
522 illegal_redecl_ = expression;
524 ASSERT(HasIllegalRedeclaration());
528 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
529 ASSERT(HasIllegalRedeclaration());
530 illegal_redecl_->Accept(visitor);
534 Declaration* Scope::CheckConflictingVarDeclarations() {
535 int length = decls_.length();
536 for (int i = 0; i < length; i++) {
537 Declaration* decl = decls_[i];
538 if (decl->mode() != VAR) continue;
539 Handle<String> name = decl->proxy()->name();
541 // Iterate through all scopes until and including the declaration scope.
542 Scope* previous = NULL;
543 Scope* current = decl->scope();
545 // There is a conflict if there exists a non-VAR binding.
546 Variable* other_var = current->variables_.Lookup(name);
547 if (other_var != NULL && other_var->mode() != VAR) {
551 current = current->outer_scope_;
552 } while (!previous->is_declaration_scope());
558 VariableProxy* Scope::CheckAssignmentToConst() {
560 if (is_extended_mode()) {
561 for (int i = 0; i < unresolved_.length(); i++) {
562 ASSERT(unresolved_[i]->var() != NULL);
563 if (unresolved_[i]->var()->is_const_mode() &&
564 unresolved_[i]->IsLValue()) {
565 return unresolved_[i];
570 // Check inner scopes.
571 for (int i = 0; i < inner_scopes_.length(); i++) {
572 VariableProxy* proxy = inner_scopes_[i]->CheckAssignmentToConst();
573 if (proxy != NULL) return proxy;
576 // No assignments to const found.
581 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
582 ZoneList<Variable*>* context_locals) {
583 ASSERT(stack_locals != NULL);
584 ASSERT(context_locals != NULL);
586 // Collect temporaries which are always allocated on the stack.
587 for (int i = 0; i < temps_.length(); i++) {
588 Variable* var = temps_[i];
589 if (var->is_used()) {
590 ASSERT(var->IsStackLocal());
591 stack_locals->Add(var);
595 // Collect declared local variables.
596 for (VariableMap::Entry* p = variables_.Start();
598 p = variables_.Next(p)) {
599 Variable* var = reinterpret_cast<Variable*>(p->value);
600 if (var->is_used()) {
601 if (var->IsStackLocal()) {
602 stack_locals->Add(var);
603 } else if (var->IsContextSlot()) {
604 context_locals->Add(var);
611 bool Scope::AllocateVariables(CompilationInfo* info,
612 AstNodeFactory<AstNullVisitor>* factory) {
613 // 1) Propagate scope information.
614 bool outer_scope_calls_non_strict_eval = false;
615 if (outer_scope_ != NULL) {
616 outer_scope_calls_non_strict_eval =
617 outer_scope_->outer_scope_calls_non_strict_eval() |
618 outer_scope_->calls_non_strict_eval();
620 PropagateScopeInfo(outer_scope_calls_non_strict_eval);
622 // 2) Resolve variables.
623 if (!ResolveVariablesRecursively(info, factory)) return false;
625 // 3) Allocate variables.
626 AllocateVariablesRecursively();
632 bool Scope::AllowsLazyCompilation() const {
633 return !force_eager_compilation_ && HasTrivialOuterContext();
637 bool Scope::HasTrivialContext() const {
638 // A function scope has a trivial context if it always is the global
639 // context. We iteratively scan out the context chain to see if
640 // there is anything that makes this scope non-trivial; otherwise we
642 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
643 if (scope->is_eval_scope()) return false;
644 if (scope->scope_inside_with_) return false;
645 if (scope->num_heap_slots_ > 0) return false;
651 bool Scope::HasTrivialOuterContext() const {
652 Scope* outer = outer_scope_;
653 if (outer == NULL) return true;
654 // Note that the outer context may be trivial in general, but the current
655 // scope may be inside a 'with' statement in which case the outer context
656 // for this scope is not trivial.
657 return !scope_inside_with_ && outer->HasTrivialContext();
661 bool Scope::AllowsLazyRecompilation() const {
662 return !force_eager_compilation_ &&
663 !TrivialDeclarationScopesBeforeWithScope();
667 bool Scope::TrivialDeclarationScopesBeforeWithScope() const {
668 Scope* outer = outer_scope_;
669 if (outer == NULL) return false;
670 outer = outer->DeclarationScope();
671 while (outer != NULL) {
672 if (outer->is_with_scope()) return true;
673 if (outer->is_declaration_scope() && outer->num_heap_slots() > 0)
675 outer = outer->outer_scope_;
681 int Scope::ContextChainLength(Scope* scope) {
683 for (Scope* s = this; s != scope; s = s->outer_scope_) {
684 ASSERT(s != NULL); // scope must be in the scope chain
685 if (s->num_heap_slots() > 0) n++;
691 Scope* Scope::DeclarationScope() {
693 while (!scope->is_declaration_scope()) {
694 scope = scope->outer_scope();
700 Handle<ScopeInfo> Scope::GetScopeInfo() {
701 if (scope_info_.is_null()) {
702 scope_info_ = ScopeInfo::Create(this);
708 void Scope::GetNestedScopeChain(
709 List<Handle<ScopeInfo> >* chain,
711 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
713 for (int i = 0; i < inner_scopes_.length(); i++) {
714 Scope* scope = inner_scopes_[i];
715 int beg_pos = scope->start_position();
716 int end_pos = scope->end_position();
717 ASSERT(beg_pos >= 0 && end_pos >= 0);
718 if (beg_pos <= position && position < end_pos) {
719 scope->GetNestedScopeChain(chain, position);
727 static const char* Header(ScopeType type) {
729 case EVAL_SCOPE: return "eval";
730 case FUNCTION_SCOPE: return "function";
731 case MODULE_SCOPE: return "module";
732 case GLOBAL_SCOPE: return "global";
733 case CATCH_SCOPE: return "catch";
734 case BLOCK_SCOPE: return "block";
735 case WITH_SCOPE: return "with";
742 static void Indent(int n, const char* str) {
743 PrintF("%*s%s", n, "", str);
747 static void PrintName(Handle<String> name) {
748 SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
753 static void PrintLocation(Variable* var) {
754 switch (var->location()) {
755 case Variable::UNALLOCATED:
757 case Variable::PARAMETER:
758 PrintF("parameter[%d]", var->index());
760 case Variable::LOCAL:
761 PrintF("local[%d]", var->index());
763 case Variable::CONTEXT:
764 PrintF("context[%d]", var->index());
766 case Variable::LOOKUP:
773 static void PrintVar(int indent, Variable* var) {
774 if (var->is_used() || !var->IsUnallocated()) {
775 Indent(indent, Variable::Mode2String(var->mode()));
777 PrintName(var->name());
780 if (var->has_forced_context_allocation()) {
781 if (!var->IsUnallocated()) PrintF(", ");
782 PrintF("forced context allocation");
789 static void PrintMap(int indent, VariableMap* map) {
790 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
791 Variable* var = reinterpret_cast<Variable*>(p->value);
792 PrintVar(indent, var);
797 void Scope::Print(int n) {
798 int n0 = (n > 0 ? n : 0);
799 int n1 = n0 + 2; // indentation
802 Indent(n0, Header(type_));
803 if (scope_name_->length() > 0) {
805 PrintName(scope_name_);
808 // Print parameters, if any.
809 if (is_function_scope()) {
811 for (int i = 0; i < params_.length(); i++) {
812 if (i > 0) PrintF(", ");
813 PrintName(params_[i]->name());
818 PrintF(" { // (%d, %d)\n", start_position(), end_position());
820 // Function name, if any (named function literals, only).
821 if (function_ != NULL) {
822 Indent(n1, "// (local) function name: ");
823 PrintName(function_->proxy()->name());
828 if (HasTrivialOuterContext()) {
829 Indent(n1, "// scope has trivial outer context\n");
831 switch (language_mode()) {
835 Indent(n1, "// strict mode scope\n");
838 Indent(n1, "// extended mode scope\n");
841 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
842 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
843 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
844 if (outer_scope_calls_non_strict_eval_) {
845 Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
847 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
848 if (num_stack_slots_ > 0) { Indent(n1, "// ");
849 PrintF("%d stack slots\n", num_stack_slots_); }
850 if (num_heap_slots_ > 0) { Indent(n1, "// ");
851 PrintF("%d heap slots\n", num_heap_slots_); }
854 Indent(n1, "// function var\n");
855 if (function_ != NULL) {
856 PrintVar(n1, function_->proxy()->var());
859 Indent(n1, "// temporary vars\n");
860 for (int i = 0; i < temps_.length(); i++) {
861 PrintVar(n1, temps_[i]);
864 Indent(n1, "// local vars\n");
865 PrintMap(n1, &variables_);
867 Indent(n1, "// dynamic vars\n");
868 if (dynamics_ != NULL) {
869 PrintMap(n1, dynamics_->GetMap(DYNAMIC));
870 PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
871 PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
874 // Print inner scopes (disable by providing negative n).
876 for (int i = 0; i < inner_scopes_.length(); i++) {
878 inner_scopes_[i]->Print(n1);
887 Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
888 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart();
889 VariableMap* map = dynamics_->GetMap(mode);
890 Variable* var = map->Lookup(name);
892 // Declare a new non-local.
893 InitializationFlag init_flag = (mode == VAR)
894 ? kCreatedInitialized : kNeedsInitialization;
895 var = map->Declare(NULL,
901 // Allocate it by giving it a dynamic lookup.
902 var->AllocateTo(Variable::LOOKUP, -1);
908 Variable* Scope::LookupRecursive(Handle<String> name,
909 BindingKind* binding_kind,
910 AstNodeFactory<AstNullVisitor>* factory) {
911 ASSERT(binding_kind != NULL);
912 // Try to find the variable in this scope.
913 Variable* var = LocalLookup(name);
915 // We found a variable and we are done. (Even if there is an 'eval' in
916 // this scope which introduces the same variable again, the resulting
917 // variable remains the same.)
919 *binding_kind = BOUND;
923 // We did not find a variable locally. Check against the function variable,
924 // if any. We can do this for all scopes, since the function variable is
925 // only present - if at all - for function scopes.
926 *binding_kind = UNBOUND;
927 var = LookupFunctionVar(name, factory);
929 *binding_kind = BOUND;
930 } else if (outer_scope_ != NULL) {
931 var = outer_scope_->LookupRecursive(name, binding_kind, factory);
932 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
933 var->ForceContextAllocation();
936 ASSERT(is_global_scope());
939 if (is_with_scope()) {
940 // The current scope is a with scope, so the variable binding can not be
941 // statically resolved. However, note that it was necessary to do a lookup
942 // in the outer scope anyway, because if a binding exists in an outer scope,
943 // the associated variable has to be marked as potentially being accessed
944 // from inside of an inner with scope (the property may not be in the 'with'
946 *binding_kind = DYNAMIC_LOOKUP;
948 } else if (calls_non_strict_eval()) {
949 // A variable binding may have been found in an outer scope, but the current
950 // scope makes a non-strict 'eval' call, so the found variable may not be
951 // the correct one (the 'eval' may introduce a binding with the same name).
952 // In that case, change the lookup result to reflect this situation.
953 if (*binding_kind == BOUND) {
954 *binding_kind = BOUND_EVAL_SHADOWED;
955 } else if (*binding_kind == UNBOUND) {
956 *binding_kind = UNBOUND_EVAL_SHADOWED;
963 bool Scope::ResolveVariable(CompilationInfo* info,
964 VariableProxy* proxy,
965 AstNodeFactory<AstNullVisitor>* factory) {
966 ASSERT(info->global_scope()->is_global_scope());
968 // If the proxy is already resolved there's nothing to do
969 // (functions and consts may be resolved by the parser).
970 if (proxy->var() != NULL) return true;
972 // Otherwise, try to resolve the variable.
973 BindingKind binding_kind;
974 Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
975 switch (binding_kind) {
977 // We found a variable binding.
980 case BOUND_EVAL_SHADOWED:
981 // We either found a variable binding that might be shadowed by eval or
982 // gave up on it (e.g. by encountering a local with the same in the outer
983 // scope which was not promoted to a context, this can happen if we use
984 // debugger to evaluate arbitrary expressions at a break point).
985 if (var->is_global()) {
986 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
987 } else if (var->is_dynamic()) {
988 var = NonLocal(proxy->name(), DYNAMIC);
990 Variable* invalidated = var;
991 var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
992 var->set_local_if_not_shadowed(invalidated);
997 // No binding has been found. Declare a variable in global scope.
998 var = info->global_scope()->DeclareGlobal(proxy->name());
1001 case UNBOUND_EVAL_SHADOWED:
1002 // No binding has been found. But some scope makes a
1003 // non-strict 'eval' call.
1004 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
1007 case DYNAMIC_LOOKUP:
1008 // The variable could not be resolved statically.
1009 var = NonLocal(proxy->name(), DYNAMIC);
1013 ASSERT(var != NULL);
1016 if (FLAG_harmony_modules) {
1019 if (FLAG_print_interface_details)
1020 PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
1022 proxy->interface()->Unify(var->interface(), &ok);
1025 if (FLAG_print_interfaces) {
1026 PrintF("SCOPES TYPE ERROR\n");
1028 proxy->interface()->Print();
1030 var->interface()->Print();
1034 // Inconsistent use of module. Throw a syntax error.
1035 // TODO(rossberg): generate more helpful error message.
1036 MessageLocation location(info->script(),
1039 Isolate* isolate = Isolate::Current();
1040 Factory* factory = isolate->factory();
1041 Handle<JSArray> array = factory->NewJSArray(1);
1042 USE(JSObject::SetElement(array, 0, var->name(), NONE, kStrictMode));
1043 Handle<Object> result =
1044 factory->NewSyntaxError("module_type_error", array);
1045 isolate->Throw(*result, &location);
1054 bool Scope::ResolveVariablesRecursively(
1055 CompilationInfo* info,
1056 AstNodeFactory<AstNullVisitor>* factory) {
1057 ASSERT(info->global_scope()->is_global_scope());
1059 // Resolve unresolved variables for this scope.
1060 for (int i = 0; i < unresolved_.length(); i++) {
1061 if (!ResolveVariable(info, unresolved_[i], factory)) return false;
1064 // Resolve unresolved variables for inner scopes.
1065 for (int i = 0; i < inner_scopes_.length(); i++) {
1066 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory))
1074 bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
1075 if (outer_scope_calls_non_strict_eval) {
1076 outer_scope_calls_non_strict_eval_ = true;
1079 bool calls_non_strict_eval =
1080 this->calls_non_strict_eval() || outer_scope_calls_non_strict_eval_;
1081 for (int i = 0; i < inner_scopes_.length(); i++) {
1082 Scope* inner_scope = inner_scopes_[i];
1083 if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
1084 inner_scope_calls_eval_ = true;
1086 if (inner_scope->force_eager_compilation_) {
1087 force_eager_compilation_ = true;
1091 return scope_calls_eval_ || inner_scope_calls_eval_;
1095 bool Scope::MustAllocate(Variable* var) {
1096 // Give var a read/write use if there is a chance it might be accessed
1097 // via an eval() call. This is only possible if the variable has a
1099 if ((var->is_this() || var->name()->length() > 0) &&
1100 (var->has_forced_context_allocation() ||
1101 scope_calls_eval_ ||
1102 inner_scope_calls_eval_ ||
1103 scope_contains_with_ ||
1105 is_block_scope())) {
1106 var->set_is_used(true);
1108 // Global variables do not need to be allocated.
1109 return !var->is_global() && var->is_used();
1113 bool Scope::MustAllocateInContext(Variable* var) {
1114 // If var is accessed from an inner scope, or if there is a possibility
1115 // that it might be accessed from the current or an inner scope (through
1116 // an eval() call or a runtime with lookup), it must be allocated in the
1119 // Exceptions: temporary variables are never allocated in a context;
1120 // catch-bound variables are always allocated in a context.
1121 if (var->mode() == TEMPORARY) return false;
1122 if (is_catch_scope() || is_block_scope() || is_module_scope()) return true;
1123 return var->has_forced_context_allocation() ||
1124 scope_calls_eval_ ||
1125 inner_scope_calls_eval_ ||
1126 scope_contains_with_ ||
1131 bool Scope::HasArgumentsParameter() {
1132 for (int i = 0; i < params_.length(); i++) {
1133 if (params_[i]->name().is_identical_to(
1134 isolate_->factory()->arguments_symbol())) {
1142 void Scope::AllocateStackSlot(Variable* var) {
1143 var->AllocateTo(Variable::LOCAL, num_stack_slots_++);
1147 void Scope::AllocateHeapSlot(Variable* var) {
1148 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++);
1152 void Scope::AllocateParameterLocals() {
1153 ASSERT(is_function_scope());
1154 Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol());
1155 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
1157 bool uses_nonstrict_arguments = false;
1159 if (MustAllocate(arguments) && !HasArgumentsParameter()) {
1160 // 'arguments' is used. Unless there is also a parameter called
1161 // 'arguments', we must be conservative and allocate all parameters to
1162 // the context assuming they will be captured by the arguments object.
1163 // If we have a parameter named 'arguments', a (new) value is always
1164 // assigned to it via the function invocation. Then 'arguments' denotes
1165 // that specific parameter value and cannot be used to access the
1166 // parameters, which is why we don't need to allocate an arguments
1167 // object in that case.
1169 // We are using 'arguments'. Tell the code generator that is needs to
1170 // allocate the arguments object by setting 'arguments_'.
1171 arguments_ = arguments;
1173 // In strict mode 'arguments' does not alias formal parameters.
1174 // Therefore in strict mode we allocate parameters as if 'arguments'
1176 uses_nonstrict_arguments = is_classic_mode();
1179 // The same parameter may occur multiple times in the parameters_ list.
1180 // If it does, and if it is not copied into the context object, it must
1181 // receive the highest parameter index for that parameter; thus iteration
1182 // order is relevant!
1183 for (int i = params_.length() - 1; i >= 0; --i) {
1184 Variable* var = params_[i];
1185 ASSERT(var->scope() == this);
1186 if (uses_nonstrict_arguments) {
1187 // Force context allocation of the parameter.
1188 var->ForceContextAllocation();
1191 if (MustAllocate(var)) {
1192 if (MustAllocateInContext(var)) {
1193 ASSERT(var->IsUnallocated() || var->IsContextSlot());
1194 if (var->IsUnallocated()) {
1195 AllocateHeapSlot(var);
1198 ASSERT(var->IsUnallocated() || var->IsParameter());
1199 if (var->IsUnallocated()) {
1200 var->AllocateTo(Variable::PARAMETER, i);
1208 void Scope::AllocateNonParameterLocal(Variable* var) {
1209 ASSERT(var->scope() == this);
1210 ASSERT(!var->IsVariable(isolate_->factory()->result_symbol()) ||
1211 !var->IsStackLocal());
1212 if (var->IsUnallocated() && MustAllocate(var)) {
1213 if (MustAllocateInContext(var)) {
1214 AllocateHeapSlot(var);
1216 AllocateStackSlot(var);
1222 void Scope::AllocateNonParameterLocals() {
1223 // All variables that have no rewrite yet are non-parameter locals.
1224 for (int i = 0; i < temps_.length(); i++) {
1225 AllocateNonParameterLocal(temps_[i]);
1228 for (VariableMap::Entry* p = variables_.Start();
1230 p = variables_.Next(p)) {
1231 Variable* var = reinterpret_cast<Variable*>(p->value);
1232 AllocateNonParameterLocal(var);
1235 // For now, function_ must be allocated at the very end. If it gets
1236 // allocated in the context, it must be the last slot in the context,
1237 // because of the current ScopeInfo implementation (see
1238 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1239 if (function_ != NULL) {
1240 AllocateNonParameterLocal(function_->proxy()->var());
1245 void Scope::AllocateVariablesRecursively() {
1246 // Allocate variables for inner scopes.
1247 for (int i = 0; i < inner_scopes_.length(); i++) {
1248 inner_scopes_[i]->AllocateVariablesRecursively();
1251 // If scope is already resolved, we still need to allocate
1252 // variables in inner scopes which might not had been resolved yet.
1253 if (already_resolved()) return;
1254 // The number of slots required for variables.
1255 num_stack_slots_ = 0;
1256 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1258 // Allocate variables for this scope.
1259 // Parameters must be allocated first, if any.
1260 if (is_function_scope()) AllocateParameterLocals();
1261 AllocateNonParameterLocals();
1263 // Force allocation of a context for this scope if necessary. For a 'with'
1264 // scope and for a function scope that makes an 'eval' call we need a context,
1265 // even if no local variables were statically allocated in the scope.
1266 // Likewise for modules.
1267 bool must_have_context = is_with_scope() || is_module_scope() ||
1268 (is_function_scope() && calls_eval());
1270 // If we didn't allocate any locals in the local context, then we only
1271 // need the minimal number of slots if we must have a context.
1272 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
1273 num_heap_slots_ = 0;
1277 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1281 int Scope::StackLocalCount() const {
1282 return num_stack_slots() -
1283 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0);
1287 int Scope::ContextLocalCount() const {
1288 if (num_heap_slots() == 0) return 0;
1289 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1290 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1293 } } // namespace v8::internal