OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/ast/scopes.h" | 5 #include "src/ast/scopes.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/parsing/parser.h" // for ParseInfo | 10 #include "src/parsing/parser.h" // for ParseInfo |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 return false; | 272 return false; |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 #ifdef DEBUG | 276 #ifdef DEBUG |
277 if (info->script_is_native() ? FLAG_print_builtin_scopes | 277 if (info->script_is_native() ? FLAG_print_builtin_scopes |
278 : FLAG_print_scopes) { | 278 : FLAG_print_scopes) { |
279 scope->Print(); | 279 scope->Print(); |
280 } | 280 } |
281 scope->CheckScopePositions(); | 281 scope->CheckScopePositions(); |
282 scope->CheckZones(); | |
283 #endif | 282 #endif |
284 | 283 |
285 info->set_scope(scope); | 284 info->set_scope(scope); |
286 return true; | 285 return true; |
287 } | 286 } |
288 | 287 |
289 void Scope::DeclareThis(AstValueFactory* ast_value_factory) { | 288 void Scope::DeclareThis(AstValueFactory* ast_value_factory) { |
290 DCHECK(!already_resolved()); | 289 DCHECK(!already_resolved()); |
291 DCHECK(is_declaration_scope()); | 290 DCHECK(is_declaration_scope()); |
292 DCHECK(has_this_declaration()); | 291 DCHECK(has_this_declaration()); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 AstNodeFactory* factory) { | 495 AstNodeFactory* factory) { |
497 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 496 if (function_ != NULL && function_->proxy()->raw_name() == name) { |
498 return function_->proxy()->var(); | 497 return function_->proxy()->var(); |
499 } else if (!scope_info_.is_null()) { | 498 } else if (!scope_info_.is_null()) { |
500 // If we are backed by a scope info, try to lookup the variable there. | 499 // If we are backed by a scope info, try to lookup the variable there. |
501 VariableMode mode; | 500 VariableMode mode; |
502 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 501 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
503 if (index < 0) return NULL; | 502 if (index < 0) return NULL; |
504 Variable* var = new (zone()) | 503 Variable* var = new (zone()) |
505 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | 504 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); |
506 DCHECK_NOT_NULL(factory); | |
507 VariableProxy* proxy = factory->NewVariableProxy(var); | 505 VariableProxy* proxy = factory->NewVariableProxy(var); |
508 VariableDeclaration* declaration = | 506 VariableDeclaration* declaration = |
509 factory->NewVariableDeclaration(proxy, mode, this, kNoSourcePosition); | 507 factory->NewVariableDeclaration(proxy, mode, this, kNoSourcePosition); |
510 DCHECK_EQ(factory->zone(), zone()); | |
511 DeclareFunctionVar(declaration); | 508 DeclareFunctionVar(declaration); |
512 var->AllocateTo(VariableLocation::CONTEXT, index); | 509 var->AllocateTo(VariableLocation::CONTEXT, index); |
513 return var; | 510 return var; |
514 } else { | 511 } else { |
515 return NULL; | 512 return NULL; |
516 } | 513 } |
517 } | 514 } |
518 | 515 |
519 | 516 |
520 Variable* Scope::Lookup(const AstRawString* name) { | 517 Variable* Scope::Lookup(const AstRawString* name) { |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 if (proxy->is_resolved() && proxy->var()->IsStackAllocated()) continue; | 882 if (proxy->is_resolved() && proxy->var()->IsStackAllocated()) continue; |
886 Handle<String> name = proxy->name(); | 883 Handle<String> name = proxy->name(); |
887 non_locals = StringSet::Add(non_locals, name); | 884 non_locals = StringSet::Add(non_locals, name); |
888 } | 885 } |
889 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 886 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
890 non_locals = scope->CollectNonLocals(non_locals); | 887 non_locals = scope->CollectNonLocals(non_locals); |
891 } | 888 } |
892 return non_locals; | 889 return non_locals; |
893 } | 890 } |
894 | 891 |
895 void Scope::AnalyzePartially(Scope* migrate_to, | |
896 AstNodeFactory* ast_node_factory) { | |
897 // Gather info from inner scopes. | |
898 PropagateScopeInfo(false); | |
899 | |
900 // Try to resolve unresolved variables for this Scope and collect those which | |
901 // cannot be resolved inside. It doesn't make sense to try to resolve them in | |
902 // the outer Scopes here, because they are incomplete. | |
903 VariableProxy* still_unresolved = nullptr; | |
904 CollectUnresolvableLocals(&still_unresolved, this); | |
905 | |
906 // Re-create the VariableProxies in the right Zone and insert them into | |
907 // migrate_to. | |
908 for (VariableProxy* proxy = still_unresolved; proxy != nullptr; | |
909 proxy = proxy->next_unresolved()) { | |
910 // Recreate the VariableProxy. | |
911 DCHECK(!proxy->is_resolved()); | |
912 VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); | |
913 migrate_to->AddUnresolved(copy); | |
914 } | |
915 | |
916 // Push scope data up to migrate_to. Note that migrate_to and this Scope | |
917 // describe the same Scope, just in different Zones. | |
918 PropagateUsageFlagsToScope(migrate_to); | |
919 if (inner_scope_calls_eval_) { | |
920 migrate_to->inner_scope_calls_eval_ = true; | |
921 } | |
922 DCHECK(!force_eager_compilation_); | |
923 migrate_to->set_start_position(start_position_); | |
924 migrate_to->set_end_position(end_position_); | |
925 migrate_to->language_mode_ = language_mode_; | |
926 outer_scope_->RemoveInnerScope(this); | |
927 DCHECK_EQ(outer_scope_, migrate_to->outer_scope_); | |
928 DCHECK_EQ(outer_scope_->zone(), migrate_to->zone()); | |
929 } | |
930 | 892 |
931 #ifdef DEBUG | 893 #ifdef DEBUG |
932 static const char* Header(ScopeType scope_type, FunctionKind function_kind, | 894 static const char* Header(ScopeType scope_type, FunctionKind function_kind, |
933 bool is_declaration_scope) { | 895 bool is_declaration_scope) { |
934 switch (scope_type) { | 896 switch (scope_type) { |
935 case EVAL_SCOPE: return "eval"; | 897 case EVAL_SCOPE: return "eval"; |
936 // TODO(adamk): Should we print concise method scopes specially? | 898 // TODO(adamk): Should we print concise method scopes specially? |
937 case FUNCTION_SCOPE: | 899 case FUNCTION_SCOPE: |
938 if (IsGeneratorFunction(function_kind)) return "function*"; | 900 if (IsGeneratorFunction(function_kind)) return "function*"; |
939 if (IsAsyncFunction(function_kind)) return "async function"; | 901 if (IsAsyncFunction(function_kind)) return "async function"; |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1128 // A scope is allowed to have invalid positions if it is hidden and has no | 1090 // A scope is allowed to have invalid positions if it is hidden and has no |
1129 // inner scopes | 1091 // inner scopes |
1130 if (!is_hidden() && inner_scope_ == nullptr) { | 1092 if (!is_hidden() && inner_scope_ == nullptr) { |
1131 CHECK_NE(kNoSourcePosition, start_position()); | 1093 CHECK_NE(kNoSourcePosition, start_position()); |
1132 CHECK_NE(kNoSourcePosition, end_position()); | 1094 CHECK_NE(kNoSourcePosition, end_position()); |
1133 } | 1095 } |
1134 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1096 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1135 scope->CheckScopePositions(); | 1097 scope->CheckScopePositions(); |
1136 } | 1098 } |
1137 } | 1099 } |
1138 | |
1139 void Scope::CheckZones() { | |
1140 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | |
1141 CHECK_EQ(scope->zone(), zone()); | |
1142 } | |
1143 } | |
1144 #endif // DEBUG | 1100 #endif // DEBUG |
1145 | 1101 |
1146 | 1102 |
1147 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { | 1103 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { |
1148 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); | 1104 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); |
1149 VariableMap* map = dynamics_->GetMap(mode); | 1105 VariableMap* map = dynamics_->GetMap(mode); |
1150 Variable* var = map->Lookup(name); | 1106 Variable* var = map->Lookup(name); |
1151 if (var == NULL) { | 1107 if (var == NULL) { |
1152 // Declare a new non-local. | 1108 // Declare a new non-local. |
1153 InitializationFlag init_flag = (mode == VAR) | 1109 InitializationFlag init_flag = (mode == VAR) |
1154 ? kCreatedInitialized : kNeedsInitialization; | 1110 ? kCreatedInitialized : kNeedsInitialization; |
1155 var = map->Declare(NULL, | 1111 var = map->Declare(NULL, |
1156 name, | 1112 name, |
1157 mode, | 1113 mode, |
1158 Variable::NORMAL, | 1114 Variable::NORMAL, |
1159 init_flag); | 1115 init_flag); |
1160 // Allocate it by giving it a dynamic lookup. | 1116 // Allocate it by giving it a dynamic lookup. |
1161 var->AllocateTo(VariableLocation::LOOKUP, -1); | 1117 var->AllocateTo(VariableLocation::LOOKUP, -1); |
1162 } | 1118 } |
1163 return var; | 1119 return var; |
1164 } | 1120 } |
1165 | 1121 |
| 1122 |
1166 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1123 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
1167 BindingKind* binding_kind, | 1124 BindingKind* binding_kind, |
1168 AstNodeFactory* factory, | 1125 AstNodeFactory* factory) { |
1169 Scope* max_outer_scope) { | |
1170 DCHECK(binding_kind != NULL); | 1126 DCHECK(binding_kind != NULL); |
1171 if (already_resolved() && is_with_scope()) { | 1127 if (already_resolved() && is_with_scope()) { |
1172 // Short-cut: if the scope is deserialized from a scope info, variable | 1128 // Short-cut: if the scope is deserialized from a scope info, variable |
1173 // allocation is already fixed. We can simply return with dynamic lookup. | 1129 // allocation is already fixed. We can simply return with dynamic lookup. |
1174 *binding_kind = DYNAMIC_LOOKUP; | 1130 *binding_kind = DYNAMIC_LOOKUP; |
1175 return NULL; | 1131 return NULL; |
1176 } | 1132 } |
1177 | 1133 |
1178 // Try to find the variable in this scope. | 1134 // Try to find the variable in this scope. |
1179 Variable* var = LookupLocal(proxy->raw_name()); | 1135 Variable* var = LookupLocal(proxy->raw_name()); |
1180 | 1136 |
1181 // We found a variable and we are done. (Even if there is an 'eval' in | 1137 // We found a variable and we are done. (Even if there is an 'eval' in |
1182 // this scope which introduces the same variable again, the resulting | 1138 // this scope which introduces the same variable again, the resulting |
1183 // variable remains the same.) | 1139 // variable remains the same.) |
1184 if (var != NULL) { | 1140 if (var != NULL) { |
1185 *binding_kind = BOUND; | 1141 *binding_kind = BOUND; |
1186 return var; | 1142 return var; |
1187 } | 1143 } |
1188 | 1144 |
1189 // We did not find a variable locally. Check against the function variable, | 1145 // We did not find a variable locally. Check against the function variable, |
1190 // if any. We can do this for all scopes, since the function variable is | 1146 // if any. We can do this for all scopes, since the function variable is |
1191 // only present - if at all - for function scopes. | 1147 // only present - if at all - for function scopes. |
1192 *binding_kind = UNBOUND; | 1148 *binding_kind = UNBOUND; |
1193 var = LookupFunctionVar(proxy->raw_name(), factory); | 1149 var = LookupFunctionVar(proxy->raw_name(), factory); |
1194 if (var != NULL) { | 1150 if (var != NULL) { |
1195 *binding_kind = BOUND; | 1151 *binding_kind = BOUND; |
1196 } else if (outer_scope_ != nullptr && this != max_outer_scope) { | 1152 } else if (outer_scope_ != NULL) { |
1197 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, | 1153 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); |
1198 max_outer_scope); | |
1199 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 1154 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
1200 var->ForceContextAllocation(); | 1155 var->ForceContextAllocation(); |
1201 } | 1156 } |
1202 } else { | 1157 } else { |
1203 DCHECK(is_script_scope() || this == max_outer_scope); | 1158 DCHECK(is_script_scope()); |
1204 } | 1159 } |
1205 | 1160 |
1206 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. | 1161 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. |
1207 // TODO(wingo): There are other variables in this category; add them. | 1162 // TODO(wingo): There are other variables in this category; add them. |
1208 bool name_can_be_shadowed = var == nullptr || !var->is_this(); | 1163 bool name_can_be_shadowed = var == nullptr || !var->is_this(); |
1209 | 1164 |
1210 if (is_with_scope() && name_can_be_shadowed) { | 1165 if (is_with_scope() && name_can_be_shadowed) { |
1211 DCHECK(!already_resolved()); | 1166 DCHECK(!already_resolved()); |
1212 // The current scope is a with scope, so the variable binding can not be | 1167 // The current scope is a with scope, so the variable binding can not be |
1213 // statically resolved. However, note that it was necessary to do a lookup | 1168 // statically resolved. However, note that it was necessary to do a lookup |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 } | 1281 } |
1327 | 1282 |
1328 // Resolve unresolved variables for inner scopes. | 1283 // Resolve unresolved variables for inner scopes. |
1329 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1284 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1330 if (!scope->ResolveVariablesRecursively(info, factory)) return false; | 1285 if (!scope->ResolveVariablesRecursively(info, factory)) return false; |
1331 } | 1286 } |
1332 | 1287 |
1333 return true; | 1288 return true; |
1334 } | 1289 } |
1335 | 1290 |
1336 void Scope::CollectUnresolvableLocals(VariableProxy** still_unresolved, | |
1337 Scope* max_outer_scope) { | |
1338 BindingKind binding_kind; | |
1339 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; | |
1340 proxy = next) { | |
1341 next = proxy->next_unresolved(); | |
1342 // Note that we pass nullptr as AstNodeFactory: this phase should not create | |
1343 // any new AstNodes, since none of the Scopes involved are backed up by | |
1344 // ScopeInfo. | |
1345 if (LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope) == | |
1346 nullptr) { | |
1347 proxy->set_next_unresolved(*still_unresolved); | |
1348 *still_unresolved = proxy; | |
1349 } | |
1350 } | |
1351 | |
1352 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | |
1353 scope->CollectUnresolvableLocals(still_unresolved, max_outer_scope); | |
1354 } | |
1355 } | |
1356 | 1291 |
1357 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { | 1292 void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { |
1358 if (outer_scope_calls_sloppy_eval) { | 1293 if (outer_scope_calls_sloppy_eval) { |
1359 outer_scope_calls_sloppy_eval_ = true; | 1294 outer_scope_calls_sloppy_eval_ = true; |
1360 } | 1295 } |
1361 | 1296 |
1362 bool calls_sloppy_eval = | 1297 bool calls_sloppy_eval = |
1363 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; | 1298 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; |
1364 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { | 1299 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { |
1365 inner->PropagateScopeInfo(calls_sloppy_eval); | 1300 inner->PropagateScopeInfo(calls_sloppy_eval); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 function_ != NULL && function_->proxy()->var()->IsContextSlot(); | 1576 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
1642 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1577 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1643 (is_function_var_in_context ? 1 : 0); | 1578 (is_function_var_in_context ? 1 : 0); |
1644 } | 1579 } |
1645 | 1580 |
1646 | 1581 |
1647 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1582 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1648 | 1583 |
1649 } // namespace internal | 1584 } // namespace internal |
1650 } // namespace v8 | 1585 } // namespace v8 |
OLD | NEW |