| 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/ast/scopeinfo.h" | 8 #include "src/ast/scopeinfo.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 function_kind_ = function_kind; | 164 function_kind_ = function_kind; |
| 165 scope_name_ = ast_value_factory_->empty_string(); | 165 scope_name_ = ast_value_factory_->empty_string(); |
| 166 dynamics_ = nullptr; | 166 dynamics_ = nullptr; |
| 167 receiver_ = nullptr; | 167 receiver_ = nullptr; |
| 168 new_target_ = nullptr; | 168 new_target_ = nullptr; |
| 169 function_ = nullptr; | 169 function_ = nullptr; |
| 170 arguments_ = nullptr; | 170 arguments_ = nullptr; |
| 171 this_function_ = nullptr; | 171 this_function_ = nullptr; |
| 172 illegal_redecl_ = nullptr; | 172 illegal_redecl_ = nullptr; |
| 173 scope_inside_with_ = false; | 173 scope_inside_with_ = false; |
| 174 scope_contains_with_ = false; | |
| 175 scope_calls_eval_ = false; | 174 scope_calls_eval_ = false; |
| 176 scope_uses_arguments_ = false; | 175 scope_uses_arguments_ = false; |
| 177 scope_uses_super_property_ = false; | 176 scope_uses_super_property_ = false; |
| 178 asm_module_ = false; | 177 asm_module_ = false; |
| 179 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; | 178 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; |
| 180 // Inherit the language mode from the parent scope. | 179 // Inherit the language mode from the parent scope. |
| 181 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; | 180 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; |
| 182 outer_scope_calls_sloppy_eval_ = false; | 181 outer_scope_calls_sloppy_eval_ = false; |
| 183 inner_scope_calls_eval_ = false; | 182 inner_scope_calls_eval_ = false; |
| 184 scope_nonlinear_ = false; | 183 scope_nonlinear_ = false; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 203 function_kind_ = scope_info->function_kind(); | 202 function_kind_ = scope_info->function_kind(); |
| 204 } | 203 } |
| 205 } | 204 } |
| 206 | 205 |
| 207 | 206 |
| 208 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 207 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
| 209 Context* context, Scope* script_scope) { | 208 Context* context, Scope* script_scope) { |
| 210 // Reconstruct the outer scope chain from a closure's context chain. | 209 // Reconstruct the outer scope chain from a closure's context chain. |
| 211 Scope* current_scope = NULL; | 210 Scope* current_scope = NULL; |
| 212 Scope* innermost_scope = NULL; | 211 Scope* innermost_scope = NULL; |
| 213 bool contains_with = false; | |
| 214 while (!context->IsNativeContext()) { | 212 while (!context->IsNativeContext()) { |
| 215 if (context->IsWithContext()) { | 213 if (context->IsWithContext()) { |
| 216 Scope* with_scope = new (zone) | 214 Scope* with_scope = new (zone) |
| 217 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), | 215 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), |
| 218 script_scope->ast_value_factory_); | 216 script_scope->ast_value_factory_); |
| 219 current_scope = with_scope; | 217 current_scope = with_scope; |
| 220 // All the inner scopes are inside a with. | 218 // All the inner scopes are inside a with. |
| 221 contains_with = true; | |
| 222 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 219 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
| 223 s->scope_inside_with_ = true; | 220 s->scope_inside_with_ = true; |
| 224 } | 221 } |
| 225 } else if (context->IsScriptContext()) { | 222 } else if (context->IsScriptContext()) { |
| 226 ScopeInfo* scope_info = context->scope_info(); | 223 ScopeInfo* scope_info = context->scope_info(); |
| 227 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, | 224 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, |
| 228 Handle<ScopeInfo>(scope_info), | 225 Handle<ScopeInfo>(scope_info), |
| 229 script_scope->ast_value_factory_); | 226 script_scope->ast_value_factory_); |
| 230 } else if (context->IsModuleContext()) { | 227 } else if (context->IsModuleContext()) { |
| 231 ScopeInfo* scope_info = context->module()->scope_info(); | 228 ScopeInfo* scope_info = context->module()->scope_info(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 245 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), | 242 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), |
| 246 script_scope->ast_value_factory_); | 243 script_scope->ast_value_factory_); |
| 247 } else { | 244 } else { |
| 248 DCHECK(context->IsCatchContext()); | 245 DCHECK(context->IsCatchContext()); |
| 249 String* name = context->catch_name(); | 246 String* name = context->catch_name(); |
| 250 current_scope = new (zone) Scope( | 247 current_scope = new (zone) Scope( |
| 251 zone, current_scope, | 248 zone, current_scope, |
| 252 script_scope->ast_value_factory_->GetString(Handle<String>(name)), | 249 script_scope->ast_value_factory_->GetString(Handle<String>(name)), |
| 253 script_scope->ast_value_factory_); | 250 script_scope->ast_value_factory_); |
| 254 } | 251 } |
| 255 if (contains_with) current_scope->RecordWithStatement(); | |
| 256 if (innermost_scope == NULL) innermost_scope = current_scope; | 252 if (innermost_scope == NULL) innermost_scope = current_scope; |
| 257 | |
| 258 // Forget about a with when we move to a context for a different function. | |
| 259 if (context->previous()->closure() != context->closure()) { | |
| 260 contains_with = false; | |
| 261 } | |
| 262 context = context->previous(); | 253 context = context->previous(); |
| 263 } | 254 } |
| 264 | 255 |
| 265 script_scope->AddInnerScope(current_scope); | 256 script_scope->AddInnerScope(current_scope); |
| 266 script_scope->PropagateScopeInfo(false); | 257 script_scope->PropagateScopeInfo(false); |
| 267 return (innermost_scope == NULL) ? script_scope : innermost_scope; | 258 return (innermost_scope == NULL) ? script_scope : innermost_scope; |
| 268 } | 259 } |
| 269 | 260 |
| 270 | 261 |
| 271 bool Scope::Analyze(ParseInfo* info) { | 262 bool Scope::Analyze(ParseInfo* info) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 } | 376 } |
| 386 | 377 |
| 387 | 378 |
| 388 void Scope::PropagateUsageFlagsToScope(Scope* other) { | 379 void Scope::PropagateUsageFlagsToScope(Scope* other) { |
| 389 DCHECK_NOT_NULL(other); | 380 DCHECK_NOT_NULL(other); |
| 390 DCHECK(!already_resolved()); | 381 DCHECK(!already_resolved()); |
| 391 DCHECK(!other->already_resolved()); | 382 DCHECK(!other->already_resolved()); |
| 392 if (uses_arguments()) other->RecordArgumentsUsage(); | 383 if (uses_arguments()) other->RecordArgumentsUsage(); |
| 393 if (uses_super_property()) other->RecordSuperPropertyUsage(); | 384 if (uses_super_property()) other->RecordSuperPropertyUsage(); |
| 394 if (calls_eval()) other->RecordEvalCall(); | 385 if (calls_eval()) other->RecordEvalCall(); |
| 395 if (scope_contains_with_) other->RecordWithStatement(); | |
| 396 } | 386 } |
| 397 | 387 |
| 398 | 388 |
| 399 Variable* Scope::LookupLocal(const AstRawString* name) { | 389 Variable* Scope::LookupLocal(const AstRawString* name) { |
| 400 Variable* result = variables_.Lookup(name); | 390 Variable* result = variables_.Lookup(name); |
| 401 if (result != NULL || scope_info_.is_null()) { | 391 if (result != NULL || scope_info_.is_null()) { |
| 402 return result; | 392 return result; |
| 403 } | 393 } |
| 404 Handle<String> name_handle = name->string(); | 394 Handle<String> name_handle = name->string(); |
| 405 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 395 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 } | 965 } |
| 976 | 966 |
| 977 // Scope info. | 967 // Scope info. |
| 978 if (HasTrivialOuterContext()) { | 968 if (HasTrivialOuterContext()) { |
| 979 Indent(n1, "// scope has trivial outer context\n"); | 969 Indent(n1, "// scope has trivial outer context\n"); |
| 980 } | 970 } |
| 981 if (is_strict(language_mode())) { | 971 if (is_strict(language_mode())) { |
| 982 Indent(n1, "// strict mode scope\n"); | 972 Indent(n1, "// strict mode scope\n"); |
| 983 } | 973 } |
| 984 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); | 974 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); |
| 985 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); | |
| 986 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); | 975 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); |
| 987 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); | 976 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); |
| 988 if (scope_uses_super_property_) | 977 if (scope_uses_super_property_) |
| 989 Indent(n1, "// scope uses 'super' property\n"); | 978 Indent(n1, "// scope uses 'super' property\n"); |
| 990 if (outer_scope_calls_sloppy_eval_) { | 979 if (outer_scope_calls_sloppy_eval_) { |
| 991 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); | 980 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
| 992 } | 981 } |
| 993 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 982 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
| 994 if (num_stack_slots_ > 0) { | 983 if (num_stack_slots_ > 0) { |
| 995 Indent(n1, "// "); | 984 Indent(n1, "// "); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 } | 1236 } |
| 1248 } | 1237 } |
| 1249 | 1238 |
| 1250 | 1239 |
| 1251 bool Scope::MustAllocate(Variable* var) { | 1240 bool Scope::MustAllocate(Variable* var) { |
| 1252 // Give var a read/write use if there is a chance it might be accessed | 1241 // Give var a read/write use if there is a chance it might be accessed |
| 1253 // via an eval() call. This is only possible if the variable has a | 1242 // via an eval() call. This is only possible if the variable has a |
| 1254 // visible name. | 1243 // visible name. |
| 1255 if ((var->is_this() || !var->raw_name()->IsEmpty()) && | 1244 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
| 1256 (var->has_forced_context_allocation() || scope_calls_eval_ || | 1245 (var->has_forced_context_allocation() || scope_calls_eval_ || |
| 1257 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || | 1246 inner_scope_calls_eval_ || is_catch_scope() || is_block_scope() || |
| 1258 is_block_scope() || is_module_scope() || is_script_scope())) { | 1247 is_module_scope() || is_script_scope())) { |
| 1259 var->set_is_used(); | 1248 var->set_is_used(); |
| 1260 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1249 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
| 1261 } | 1250 } |
| 1262 // Global variables do not need to be allocated. | 1251 // Global variables do not need to be allocated. |
| 1263 return !var->IsGlobalObjectProperty() && var->is_used(); | 1252 return !var->IsGlobalObjectProperty() && var->is_used(); |
| 1264 } | 1253 } |
| 1265 | 1254 |
| 1266 | 1255 |
| 1267 bool Scope::MustAllocateInContext(Variable* var) { | 1256 bool Scope::MustAllocateInContext(Variable* var) { |
| 1268 // If var is accessed from an inner scope, or if there is a possibility | 1257 // If var is accessed from an inner scope, or if there is a possibility |
| 1269 // that it might be accessed from the current or an inner scope (through | 1258 // that it might be accessed from the current or an inner scope (through |
| 1270 // an eval() call or a runtime with lookup), it must be allocated in the | 1259 // an eval() call or a runtime with lookup), it must be allocated in the |
| 1271 // context. | 1260 // context. |
| 1272 // | 1261 // |
| 1273 // Exceptions: If the scope as a whole has forced context allocation, all | 1262 // Exceptions: If the scope as a whole has forced context allocation, all |
| 1274 // variables will have context allocation, even temporaries. Otherwise | 1263 // variables will have context allocation, even temporaries. Otherwise |
| 1275 // temporary variables are always stack-allocated. Catch-bound variables are | 1264 // temporary variables are always stack-allocated. Catch-bound variables are |
| 1276 // always context-allocated. | 1265 // always context-allocated. |
| 1277 if (has_forced_context_allocation()) return true; | 1266 if (has_forced_context_allocation()) return true; |
| 1278 if (var->mode() == TEMPORARY) return false; | 1267 if (var->mode() == TEMPORARY) return false; |
| 1279 if (is_catch_scope() || is_module_scope()) return true; | 1268 if (is_catch_scope() || is_module_scope()) return true; |
| 1280 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; | 1269 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; |
| 1281 return var->has_forced_context_allocation() || | 1270 return var->has_forced_context_allocation() || scope_calls_eval_ || |
| 1282 scope_calls_eval_ || | 1271 inner_scope_calls_eval_; |
| 1283 inner_scope_calls_eval_ || | |
| 1284 scope_contains_with_; | |
| 1285 } | 1272 } |
| 1286 | 1273 |
| 1287 | 1274 |
| 1288 bool Scope::HasArgumentsParameter(Isolate* isolate) { | 1275 bool Scope::HasArgumentsParameter(Isolate* isolate) { |
| 1289 for (int i = 0; i < params_.length(); i++) { | 1276 for (int i = 0; i < params_.length(); i++) { |
| 1290 if (params_[i]->name().is_identical_to( | 1277 if (params_[i]->name().is_identical_to( |
| 1291 isolate->factory()->arguments_string())) { | 1278 isolate->factory()->arguments_string())) { |
| 1292 return true; | 1279 return true; |
| 1293 } | 1280 } |
| 1294 } | 1281 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 function_ != NULL && function_->proxy()->var()->IsContextSlot(); | 1517 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
| 1531 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1518 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1532 (is_function_var_in_context ? 1 : 0); | 1519 (is_function_var_in_context ? 1 : 0); |
| 1533 } | 1520 } |
| 1534 | 1521 |
| 1535 | 1522 |
| 1536 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1523 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1537 | 1524 |
| 1538 } // namespace internal | 1525 } // namespace internal |
| 1539 } // namespace v8 | 1526 } // namespace v8 |
| OLD | NEW |