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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/scopes.h" | 7 #include "src/scopes.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 receiver_ = NULL; | 156 receiver_ = NULL; |
157 function_ = NULL; | 157 function_ = NULL; |
158 arguments_ = NULL; | 158 arguments_ = NULL; |
159 illegal_redecl_ = NULL; | 159 illegal_redecl_ = NULL; |
160 scope_inside_with_ = false; | 160 scope_inside_with_ = false; |
161 scope_contains_with_ = false; | 161 scope_contains_with_ = false; |
162 scope_calls_eval_ = false; | 162 scope_calls_eval_ = false; |
163 scope_uses_arguments_ = false; | 163 scope_uses_arguments_ = false; |
164 scope_uses_super_property_ = false; | 164 scope_uses_super_property_ = false; |
165 scope_uses_super_constructor_call_ = false; | 165 scope_uses_super_constructor_call_ = false; |
166 scope_uses_this_ = false; | |
167 asm_module_ = false; | 166 asm_module_ = false; |
168 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; | 167 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; |
169 // Inherit the strict mode from the parent scope. | 168 // Inherit the strict mode from the parent scope. |
170 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; | 169 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; |
171 outer_scope_calls_sloppy_eval_ = false; | 170 outer_scope_calls_sloppy_eval_ = false; |
172 inner_scope_calls_eval_ = false; | 171 inner_scope_calls_eval_ = false; |
173 inner_scope_uses_arguments_ = false; | 172 inner_scope_uses_arguments_ = false; |
174 inner_scope_uses_this_ = false; | |
175 inner_scope_uses_super_property_ = false; | 173 inner_scope_uses_super_property_ = false; |
176 inner_scope_uses_super_constructor_call_ = false; | 174 inner_scope_uses_super_constructor_call_ = false; |
177 force_eager_compilation_ = false; | 175 force_eager_compilation_ = false; |
178 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) | 176 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) |
179 ? outer_scope->has_forced_context_allocation() : false; | 177 ? outer_scope->has_forced_context_allocation() : false; |
180 num_var_or_const_ = 0; | 178 num_var_or_const_ = 0; |
181 num_stack_slots_ = 0; | 179 num_stack_slots_ = 0; |
182 num_heap_slots_ = 0; | 180 num_heap_slots_ = 0; |
183 num_modules_ = 0; | 181 num_modules_ = 0; |
184 module_var_ = NULL, | 182 module_var_ = NULL, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 } | 301 } |
304 | 302 |
305 // Declare convenience variables. | 303 // Declare convenience variables. |
306 // Declare and allocate receiver (even for the script scope, and even | 304 // Declare and allocate receiver (even for the script scope, and even |
307 // if naccesses_ == 0). | 305 // if naccesses_ == 0). |
308 // NOTE: When loading parameters in the script scope, we must take | 306 // NOTE: When loading parameters in the script scope, we must take |
309 // care not to access them as properties of the global object, but | 307 // care not to access them as properties of the global object, but |
310 // instead load them directly from the stack. Currently, the only | 308 // instead load them directly from the stack. Currently, the only |
311 // such parameter is 'this' which is passed on the stack when | 309 // such parameter is 'this' which is passed on the stack when |
312 // invoking scripts | 310 // invoking scripts |
313 if (is_declaration_scope()) { | 311 if (has_this_declaration()) { |
314 Variable* var = | 312 Variable* var = |
315 variables_.Declare(this, | 313 variables_.Declare(this, |
316 ast_value_factory_->this_string(), | 314 ast_value_factory_->this_string(), |
317 VAR, | 315 VAR, |
318 false, | 316 false, |
319 Variable::THIS, | 317 Variable::THIS, |
320 kCreatedInitialized); | 318 kCreatedInitialized); |
321 var->AllocateTo(Variable::PARAMETER, -1); | |
322 receiver_ = var; | 319 receiver_ = var; |
323 } else { | |
324 DCHECK(outer_scope() != NULL); | |
325 receiver_ = outer_scope()->receiver(); | |
326 } | 320 } |
327 | 321 |
328 if (is_function_scope()) { | 322 if (is_function_scope()) { |
329 // Declare 'arguments' variable which exists in all functions. | 323 // Declare 'arguments' variable which exists in all functions. |
330 // Note that it might never be accessed, in which case it won't be | 324 // Note that it might never be accessed, in which case it won't be |
331 // allocated during variable allocation. | 325 // allocated during variable allocation. |
332 variables_.Declare(this, | 326 variables_.Declare(this, |
333 ast_value_factory_->arguments_string(), | 327 ast_value_factory_->arguments_string(), |
334 VAR, | 328 VAR, |
335 true, | 329 true, |
(...skipping 27 matching lines...) Expand all Loading... | |
363 // Move unresolved variables | 357 // Move unresolved variables |
364 for (int i = 0; i < unresolved_.length(); i++) { | 358 for (int i = 0; i < unresolved_.length(); i++) { |
365 outer_scope()->unresolved_.Add(unresolved_[i], zone()); | 359 outer_scope()->unresolved_.Add(unresolved_[i], zone()); |
366 } | 360 } |
367 | 361 |
368 // Propagate usage flags to outer scope. | 362 // Propagate usage flags to outer scope. |
369 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); | 363 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); |
370 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); | 364 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); |
371 if (uses_super_constructor_call()) | 365 if (uses_super_constructor_call()) |
372 outer_scope_->RecordSuperConstructorCallUsage(); | 366 outer_scope_->RecordSuperConstructorCallUsage(); |
373 if (uses_this()) outer_scope_->RecordThisUsage(); | |
374 | 367 |
375 return NULL; | 368 return NULL; |
376 } | 369 } |
377 | 370 |
378 | 371 |
379 Variable* Scope::LookupLocal(const AstRawString* name) { | 372 Variable* Scope::LookupLocal(const AstRawString* name) { |
380 Variable* result = variables_.Lookup(name); | 373 Variable* result = variables_.Lookup(name); |
381 if (result != NULL || scope_info_.is_null()) { | 374 if (result != NULL || scope_info_.is_null()) { |
382 return result; | 375 return result; |
383 } | 376 } |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
887 Indent(n1, "// strict mode scope\n"); | 880 Indent(n1, "// strict mode scope\n"); |
888 } | 881 } |
889 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); | 882 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); |
890 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); | 883 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); |
891 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); | 884 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); |
892 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); | 885 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); |
893 if (scope_uses_super_property_) | 886 if (scope_uses_super_property_) |
894 Indent(n1, "// scope uses 'super' property\n"); | 887 Indent(n1, "// scope uses 'super' property\n"); |
895 if (scope_uses_super_constructor_call_) | 888 if (scope_uses_super_constructor_call_) |
896 Indent(n1, "// scope uses 'super' constructor\n"); | 889 Indent(n1, "// scope uses 'super' constructor\n"); |
897 if (scope_uses_this_) Indent(n1, "// scope uses 'this'\n"); | |
898 if (inner_scope_uses_arguments_) { | 890 if (inner_scope_uses_arguments_) { |
899 Indent(n1, "// inner scope uses 'arguments'\n"); | 891 Indent(n1, "// inner scope uses 'arguments'\n"); |
900 } | 892 } |
901 if (inner_scope_uses_super_property_) | 893 if (inner_scope_uses_super_property_) |
902 Indent(n1, "// inner scope uses 'super' property\n"); | 894 Indent(n1, "// inner scope uses 'super' property\n"); |
903 if (inner_scope_uses_super_constructor_call_) { | 895 if (inner_scope_uses_super_constructor_call_) { |
904 Indent(n1, "// inner scope uses 'super' constructor\n"); | 896 Indent(n1, "// inner scope uses 'super' constructor\n"); |
905 } | 897 } |
906 if (inner_scope_uses_this_) Indent(n1, "// inner scope uses 'this'\n"); | |
907 if (outer_scope_calls_sloppy_eval_) { | 898 if (outer_scope_calls_sloppy_eval_) { |
908 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); | 899 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
909 } | 900 } |
910 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 901 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
911 if (num_stack_slots_ > 0) { Indent(n1, "// "); | 902 if (num_stack_slots_ > 0) { Indent(n1, "// "); |
912 PrintF("%d stack slots\n", num_stack_slots_); } | 903 PrintF("%d stack slots\n", num_stack_slots_); } |
913 if (num_heap_slots_ > 0) { Indent(n1, "// "); | 904 if (num_heap_slots_ > 0) { Indent(n1, "// "); |
914 PrintF("%d heap slots\n", num_heap_slots_); } | 905 PrintF("%d heap slots\n", num_heap_slots_); } |
915 | 906 |
916 // Print locals. | 907 // Print locals. |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1176 inner_scope_uses_arguments_ = true; | 1167 inner_scope_uses_arguments_ = true; |
1177 } | 1168 } |
1178 if (inner->scope_uses_super_property_ || | 1169 if (inner->scope_uses_super_property_ || |
1179 inner->inner_scope_uses_super_property_) { | 1170 inner->inner_scope_uses_super_property_) { |
1180 inner_scope_uses_super_property_ = true; | 1171 inner_scope_uses_super_property_ = true; |
1181 } | 1172 } |
1182 if (inner->uses_super_constructor_call() || | 1173 if (inner->uses_super_constructor_call() || |
1183 inner->inner_scope_uses_super_constructor_call_) { | 1174 inner->inner_scope_uses_super_constructor_call_) { |
1184 inner_scope_uses_super_constructor_call_ = true; | 1175 inner_scope_uses_super_constructor_call_ = true; |
1185 } | 1176 } |
1186 if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) { | |
1187 inner_scope_uses_this_ = true; | |
1188 } | |
1189 } | 1177 } |
1178 | |
wingo
2015/02/04 10:02:13
extra whitespace
aperez
2015/02/04 21:00:42
Acknowledged.
| |
1190 if (inner->force_eager_compilation_) { | 1179 if (inner->force_eager_compilation_) { |
1191 force_eager_compilation_ = true; | 1180 force_eager_compilation_ = true; |
1192 } | 1181 } |
1193 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { | 1182 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { |
1194 inner->asm_function_ = true; | 1183 inner->asm_function_ = true; |
1195 } | 1184 } |
1196 } | 1185 } |
1197 } | 1186 } |
1198 | 1187 |
1199 | 1188 |
1200 bool Scope::MustAllocate(Variable* var) { | 1189 bool Scope::MustAllocate(Variable* var) { |
1201 // Give var a read/write use if there is a chance it might be accessed | 1190 // Give var a read/write use if there is a chance it might be accessed |
1202 // via an eval() call. This is only possible if the variable has a | 1191 // via an eval() call. This is only possible if the variable has a |
1203 // visible name. | 1192 // visible name. |
1204 if ((var->is_this() || !var->raw_name()->IsEmpty()) && | 1193 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
1205 (var->has_forced_context_allocation() || | 1194 (var->has_forced_context_allocation() || |
1206 scope_calls_eval_ || | 1195 scope_calls_eval_ || |
1207 inner_scope_calls_eval_ || | 1196 inner_scope_calls_eval_ || |
1208 scope_contains_with_ || | 1197 scope_contains_with_ || |
1209 is_catch_scope() || | 1198 is_catch_scope() || |
1210 is_block_scope() || | 1199 is_block_scope() || |
1211 is_module_scope() || | 1200 is_module_scope() || |
1212 is_script_scope())) { | 1201 is_script_scope())) { |
1213 var->set_is_used(); | 1202 var->set_is_used(); |
1214 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1203 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
1215 } | 1204 } |
1216 // Global variables do not need to be allocated. | 1205 // Global variables do not need to be allocated, except the receiver |
1217 return !var->IsGlobalObjectProperty() && var->is_used(); | 1206 // which is not preallocated. |
wingo
2015/02/04 10:02:13
Confusing comment. Also I think the conditional
aperez
2015/02/04 21:00:42
Acknowledged.
| |
1207 return (var->is_this() || !var->IsGlobalObjectProperty()) && var->is_used(); | |
1218 } | 1208 } |
1219 | 1209 |
1220 | 1210 |
1221 bool Scope::MustAllocateInContext(Variable* var) { | 1211 bool Scope::MustAllocateInContext(Variable* var) { |
1222 // If var is accessed from an inner scope, or if there is a possibility | 1212 // If var is accessed from an inner scope, or if there is a possibility |
1223 // that it might be accessed from the current or an inner scope (through | 1213 // that it might be accessed from the current or an inner scope (through |
1224 // an eval() call or a runtime with lookup), it must be allocated in the | 1214 // an eval() call or a runtime with lookup), it must be allocated in the |
1225 // context. | 1215 // context. |
1226 // | 1216 // |
1227 // Exceptions: If the scope as a whole has forced context allocation, all | 1217 // Exceptions: If the scope as a whole has forced context allocation, all |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1292 // If it does, and if it is not copied into the context object, it must | 1282 // If it does, and if it is not copied into the context object, it must |
1293 // receive the highest parameter index for that parameter; thus iteration | 1283 // receive the highest parameter index for that parameter; thus iteration |
1294 // order is relevant! | 1284 // order is relevant! |
1295 for (int i = params_.length() - 1; i >= 0; --i) { | 1285 for (int i = params_.length() - 1; i >= 0; --i) { |
1296 Variable* var = params_[i]; | 1286 Variable* var = params_[i]; |
1297 DCHECK(var->scope() == this); | 1287 DCHECK(var->scope() == this); |
1298 if (uses_sloppy_arguments || has_forced_context_allocation()) { | 1288 if (uses_sloppy_arguments || has_forced_context_allocation()) { |
1299 // Force context allocation of the parameter. | 1289 // Force context allocation of the parameter. |
1300 var->ForceContextAllocation(); | 1290 var->ForceContextAllocation(); |
1301 } | 1291 } |
1292 AllocateParameter(var, i); | |
1293 } | |
1294 } | |
1302 | 1295 |
1303 if (MustAllocate(var)) { | 1296 |
1304 if (MustAllocateInContext(var)) { | 1297 void Scope::AllocateReceiver() { |
1305 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | 1298 DCHECK(receiver()); |
1306 if (var->IsUnallocated()) { | 1299 DCHECK(receiver()->scope() == this); |
wingo
2015/02/04 10:02:13
the second DCHECK is sufficient, I think, if we ad
aperez
2015/02/04 21:00:42
Acknowledged.
| |
1307 AllocateHeapSlot(var); | 1300 |
1308 } | 1301 if (has_forced_context_allocation()) { |
1309 } else { | 1302 // Force context allocation of the receiver. |
1310 DCHECK(var->IsUnallocated() || var->IsParameter()); | 1303 receiver()->ForceContextAllocation(); |
1311 if (var->IsUnallocated()) { | 1304 } |
1312 var->AllocateTo(Variable::PARAMETER, i); | 1305 AllocateParameter(receiver(), -1); |
1313 } | 1306 } |
1307 | |
1308 | |
1309 void Scope::AllocateParameter(Variable* var, int index) { | |
1310 if (MustAllocate(var)) { | |
1311 if (MustAllocateInContext(var)) { | |
1312 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | |
1313 if (var->IsUnallocated()) { | |
1314 AllocateHeapSlot(var); | |
1315 } | |
1316 } else { | |
1317 DCHECK(var->IsUnallocated() || var->IsParameter()); | |
1318 if (var->IsUnallocated()) { | |
1319 var->AllocateTo(Variable::PARAMETER, index); | |
1314 } | 1320 } |
1315 } | 1321 } |
1316 } | 1322 } |
1317 } | 1323 } |
1318 | 1324 |
1319 | 1325 |
1320 void Scope::AllocateNonParameterLocal(Variable* var) { | 1326 void Scope::AllocateNonParameterLocal(Variable* var) { |
1321 DCHECK(var->scope() == this); | 1327 DCHECK(var->scope() == this); |
1322 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || | 1328 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || |
1323 !var->IsStackLocal()); | 1329 !var->IsStackLocal()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1372 | 1378 |
1373 // If scope is already resolved, we still need to allocate | 1379 // If scope is already resolved, we still need to allocate |
1374 // variables in inner scopes which might not had been resolved yet. | 1380 // variables in inner scopes which might not had been resolved yet. |
1375 if (already_resolved()) return; | 1381 if (already_resolved()) return; |
1376 // The number of slots required for variables. | 1382 // The number of slots required for variables. |
1377 num_stack_slots_ = 0; | 1383 num_stack_slots_ = 0; |
1378 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1384 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
1379 | 1385 |
1380 // Allocate variables for this scope. | 1386 // Allocate variables for this scope. |
1381 // Parameters must be allocated first, if any. | 1387 // Parameters must be allocated first, if any. |
1388 if (has_this_declaration()) AllocateReceiver(); | |
1382 if (is_function_scope()) AllocateParameterLocals(); | 1389 if (is_function_scope()) AllocateParameterLocals(); |
1383 AllocateNonParameterLocals(); | 1390 AllocateNonParameterLocals(); |
1384 | 1391 |
1385 // Force allocation of a context for this scope if necessary. For a 'with' | 1392 // Force allocation of a context for this scope if necessary. For a 'with' |
1386 // scope and for a function scope that makes an 'eval' call we need a context, | 1393 // scope and for a function scope that makes an 'eval' call we need a context, |
1387 // even if no local variables were statically allocated in the scope. | 1394 // even if no local variables were statically allocated in the scope. |
1388 // Likewise for modules. | 1395 // Likewise for modules. |
1389 bool must_have_context = is_with_scope() || is_module_scope() || | 1396 bool must_have_context = is_with_scope() || is_module_scope() || |
1390 (is_function_scope() && calls_eval()); | 1397 (is_function_scope() && calls_eval()); |
1391 | 1398 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1423 } | 1430 } |
1424 | 1431 |
1425 | 1432 |
1426 int Scope::ContextLocalCount() const { | 1433 int Scope::ContextLocalCount() const { |
1427 if (num_heap_slots() == 0) return 0; | 1434 if (num_heap_slots() == 0) return 0; |
1428 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1435 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1429 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1436 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1430 } | 1437 } |
1431 | 1438 |
1432 } } // namespace v8::internal | 1439 } } // namespace v8::internal |
OLD | NEW |