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 |