Chromium Code Reviews| 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 |