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/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/parser.h" | 10 #include "src/parser.h" |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 scope_type_ = scope_type; | 153 scope_type_ = scope_type; |
154 function_kind_ = function_kind; | 154 function_kind_ = function_kind; |
155 block_scope_is_class_scope_ = false; | 155 block_scope_is_class_scope_ = false; |
156 scope_name_ = ast_value_factory_->empty_string(); | 156 scope_name_ = ast_value_factory_->empty_string(); |
157 dynamics_ = nullptr; | 157 dynamics_ = nullptr; |
158 receiver_ = nullptr; | 158 receiver_ = nullptr; |
159 new_target_ = nullptr; | 159 new_target_ = nullptr; |
160 function_ = nullptr; | 160 function_ = nullptr; |
161 arguments_ = nullptr; | 161 arguments_ = nullptr; |
162 home_object_ = nullptr; | 162 home_object_ = nullptr; |
| 163 this_function_ = nullptr; |
163 illegal_redecl_ = nullptr; | 164 illegal_redecl_ = nullptr; |
164 scope_inside_with_ = false; | 165 scope_inside_with_ = false; |
165 scope_contains_with_ = false; | 166 scope_contains_with_ = false; |
166 scope_calls_eval_ = false; | 167 scope_calls_eval_ = false; |
167 scope_uses_arguments_ = false; | 168 scope_uses_arguments_ = false; |
168 scope_uses_super_property_ = false; | 169 scope_uses_super_property_ = false; |
169 asm_module_ = false; | 170 asm_module_ = false; |
170 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; | 171 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; |
171 // Inherit the language mode from the parent scope. | 172 // Inherit the language mode from the parent scope. |
172 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; | 173 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 | 302 |
302 // Add this scope as a new inner scope of the outer scope. | 303 // Add this scope as a new inner scope of the outer scope. |
303 if (outer_scope_ != NULL) { | 304 if (outer_scope_ != NULL) { |
304 outer_scope_->inner_scopes_.Add(this, zone()); | 305 outer_scope_->inner_scopes_.Add(this, zone()); |
305 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); | 306 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); |
306 } else { | 307 } else { |
307 scope_inside_with_ = is_with_scope(); | 308 scope_inside_with_ = is_with_scope(); |
308 } | 309 } |
309 | 310 |
310 // Declare convenience variables and the receiver. | 311 // Declare convenience variables and the receiver. |
311 if (is_declaration_scope()) { | 312 if (is_declaration_scope() && has_this_declaration()) { |
312 DCHECK(!subclass_constructor || is_function_scope()); | 313 Variable* var = variables_.Declare( |
313 if (has_this_declaration()) { | 314 this, ast_value_factory_->this_string(), |
314 Variable* var = variables_.Declare( | 315 subclass_constructor ? CONST : VAR, Variable::THIS, |
315 this, ast_value_factory_->this_string(), | 316 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); |
316 subclass_constructor ? CONST : VAR, Variable::THIS, | 317 receiver_ = var; |
317 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); | 318 } |
318 receiver_ = var; | 319 |
| 320 if (is_function_scope()) { |
| 321 if (!is_arrow_scope()) { |
| 322 // Declare 'arguments' variable which exists in all non arrow functions. |
| 323 // Note that it might never be accessed, in which case it won't be |
| 324 // allocated during variable allocation. |
| 325 variables_.Declare(this, ast_value_factory_->arguments_string(), VAR, |
| 326 Variable::ARGUMENTS, kCreatedInitialized); |
319 } | 327 } |
320 | 328 |
321 if (subclass_constructor) { | 329 if (subclass_constructor) { |
322 new_target_ = | 330 DCHECK(!is_arrow_scope()); |
323 variables_.Declare(this, ast_value_factory_->new_target_string(), | 331 variables_.Declare(this, ast_value_factory_->new_target_string(), CONST, |
324 CONST, Variable::NEW_TARGET, kCreatedInitialized); | 332 Variable::NORMAL, kCreatedInitialized); |
325 new_target_->AllocateTo(Variable::PARAMETER, -2); | |
326 new_target_->set_is_used(); | |
327 } | 333 } |
328 } | |
329 | 334 |
330 if (is_function_scope() && !is_arrow_scope()) { | 335 if (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) || |
331 // Declare 'arguments' variable which exists in all non arrow functions. | 336 IsAccessorFunction(function_kind_)) { |
332 // Note that it might never be accessed, in which case it won't be | 337 DCHECK(!is_arrow_scope()); |
333 // allocated during variable allocation. | 338 // Declare '.home_object' variable which exists in all methods. |
334 variables_.Declare(this, | 339 // Note that it might never be accessed, in which case it won't be |
335 ast_value_factory_->arguments_string(), | 340 // allocated during variable allocation. |
336 VAR, | 341 variables_.Declare(this, ast_value_factory_->home_object_string(), CONST, |
337 Variable::ARGUMENTS, | 342 Variable::NORMAL, kCreatedInitialized); |
338 kCreatedInitialized); | 343 } |
339 } | |
340 | 344 |
341 if (is_function_scope() && | 345 if (IsSubclassConstructor(function_kind_)) { |
342 (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) || | 346 DCHECK(!is_arrow_scope()); |
343 IsAccessorFunction(function_kind_))) { | 347 variables_.Declare(this, ast_value_factory_->this_function_string(), |
344 DCHECK(!is_arrow_scope()); | 348 CONST, Variable::NORMAL, kCreatedInitialized); |
345 // Declare '.home_object' variable which exists in all methods. | 349 } |
346 // Note that it might never be accessed, in which case it won't be | |
347 // allocated during variable allocation. | |
348 variables_.Declare(this, ast_value_factory_->home_object_string(), VAR, | |
349 Variable::NORMAL, kCreatedInitialized); | |
350 } | 350 } |
351 } | 351 } |
352 | 352 |
353 | 353 |
354 Scope* Scope::FinalizeBlockScope() { | 354 Scope* Scope::FinalizeBlockScope() { |
355 DCHECK(is_block_scope()); | 355 DCHECK(is_block_scope()); |
356 DCHECK(internals_.is_empty()); | 356 DCHECK(internals_.is_empty()); |
357 DCHECK(temps_.is_empty()); | 357 DCHECK(temps_.is_empty()); |
358 DCHECK(params_.is_empty()); | 358 DCHECK(params_.is_empty()); |
359 | 359 |
(...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 inner->asm_function_ = true; | 1304 inner->asm_function_ = true; |
1305 } | 1305 } |
1306 } | 1306 } |
1307 } | 1307 } |
1308 | 1308 |
1309 | 1309 |
1310 bool Scope::MustAllocate(Variable* var) { | 1310 bool Scope::MustAllocate(Variable* var) { |
1311 // Give var a read/write use if there is a chance it might be accessed | 1311 // Give var a read/write use if there is a chance it might be accessed |
1312 // via an eval() call. This is only possible if the variable has a | 1312 // via an eval() call. This is only possible if the variable has a |
1313 // visible name. | 1313 // visible name. |
1314 if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && | 1314 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
1315 (var->has_forced_context_allocation() || scope_calls_eval_ || | 1315 (var->has_forced_context_allocation() || scope_calls_eval_ || |
1316 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || | 1316 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || |
1317 is_block_scope() || is_module_scope() || is_script_scope())) { | 1317 is_block_scope() || is_module_scope() || is_script_scope())) { |
1318 var->set_is_used(); | 1318 var->set_is_used(); |
1319 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1319 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
1320 } | 1320 } |
1321 // Global variables do not need to be allocated. | 1321 // Global variables do not need to be allocated. |
1322 return !var->IsGlobalObjectProperty() && var->is_used(); | 1322 return !var->IsGlobalObjectProperty() && var->is_used(); |
1323 } | 1323 } |
1324 | 1324 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 // In strict mode 'arguments' does not alias formal parameters. | 1396 // In strict mode 'arguments' does not alias formal parameters. |
1397 // Therefore in strict mode we allocate parameters as if 'arguments' | 1397 // Therefore in strict mode we allocate parameters as if 'arguments' |
1398 // were not used. | 1398 // were not used. |
1399 uses_sloppy_arguments = is_sloppy(language_mode()); | 1399 uses_sloppy_arguments = is_sloppy(language_mode()); |
1400 } | 1400 } |
1401 | 1401 |
1402 if (rest_parameter_ && !MustAllocate(rest_parameter_)) { | 1402 if (rest_parameter_ && !MustAllocate(rest_parameter_)) { |
1403 rest_parameter_ = NULL; | 1403 rest_parameter_ = NULL; |
1404 } | 1404 } |
1405 | 1405 |
1406 Variable* home_object_var = | |
1407 LookupLocal(ast_value_factory_->home_object_string()); | |
1408 if (home_object_var != nullptr && uses_super_property() && | |
1409 MustAllocate(home_object_var)) { | |
1410 // TODO(arv): super() uses a SuperReference so it generates a VariableProxy | |
1411 // for the .home_object which makes it look like we need to allocate the | |
1412 // home_object_var. | |
1413 // Consider splitting the AST node into 2 different nodes since the | |
1414 // semantics is just so different. | |
1415 home_object_ = home_object_var; | |
1416 } | |
1417 | |
1418 // The same parameter may occur multiple times in the parameters_ list. | 1406 // The same parameter may occur multiple times in the parameters_ list. |
1419 // If it does, and if it is not copied into the context object, it must | 1407 // If it does, and if it is not copied into the context object, it must |
1420 // receive the highest parameter index for that parameter; thus iteration | 1408 // receive the highest parameter index for that parameter; thus iteration |
1421 // order is relevant! | 1409 // order is relevant! |
1422 for (int i = params_.length() - 1; i >= 0; --i) { | 1410 for (int i = params_.length() - 1; i >= 0; --i) { |
1423 Variable* var = params_[i]; | 1411 Variable* var = params_[i]; |
1424 if (var == rest_parameter_) continue; | 1412 if (var == rest_parameter_) continue; |
1425 | 1413 |
1426 DCHECK(var->scope() == this); | 1414 DCHECK(var->scope() == this); |
1427 if (uses_sloppy_arguments || has_forced_context_allocation()) { | 1415 if (uses_sloppy_arguments || has_forced_context_allocation()) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1496 vars.Sort(VarAndOrder::Compare); | 1484 vars.Sort(VarAndOrder::Compare); |
1497 int var_count = vars.length(); | 1485 int var_count = vars.length(); |
1498 for (int i = 0; i < var_count; i++) { | 1486 for (int i = 0; i < var_count; i++) { |
1499 AllocateNonParameterLocal(isolate, vars[i].var()); | 1487 AllocateNonParameterLocal(isolate, vars[i].var()); |
1500 } | 1488 } |
1501 | 1489 |
1502 // For now, function_ must be allocated at the very end. If it gets | 1490 // For now, function_ must be allocated at the very end. If it gets |
1503 // allocated in the context, it must be the last slot in the context, | 1491 // allocated in the context, it must be the last slot in the context, |
1504 // because of the current ScopeInfo implementation (see | 1492 // because of the current ScopeInfo implementation (see |
1505 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1493 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
1506 if (function_ != NULL) { | 1494 if (function_ != nullptr) { |
1507 AllocateNonParameterLocal(isolate, function_->proxy()->var()); | 1495 AllocateNonParameterLocal(isolate, function_->proxy()->var()); |
1508 } | 1496 } |
1509 | 1497 |
1510 if (rest_parameter_) { | 1498 if (rest_parameter_ != nullptr) { |
1511 AllocateNonParameterLocal(isolate, rest_parameter_); | 1499 AllocateNonParameterLocal(isolate, rest_parameter_); |
1512 } | 1500 } |
| 1501 |
| 1502 Variable* home_object_var = |
| 1503 LookupLocal(ast_value_factory_->home_object_string()); |
| 1504 if (home_object_var != nullptr && MustAllocate(home_object_var)) { |
| 1505 home_object_ = home_object_var; |
| 1506 } |
| 1507 |
| 1508 Variable* new_target_var = |
| 1509 LookupLocal(ast_value_factory_->new_target_string()); |
| 1510 if (new_target_var != nullptr && MustAllocate(new_target_var)) { |
| 1511 new_target_ = new_target_var; |
| 1512 } |
| 1513 |
| 1514 Variable* this_function_var = |
| 1515 LookupLocal(ast_value_factory_->this_function_string()); |
| 1516 if (this_function_var != nullptr && MustAllocate(this_function_var)) { |
| 1517 this_function_ = this_function_var; |
| 1518 } |
1513 } | 1519 } |
1514 | 1520 |
1515 | 1521 |
1516 void Scope::AllocateVariablesRecursively(Isolate* isolate) { | 1522 void Scope::AllocateVariablesRecursively(Isolate* isolate) { |
1517 if (!already_resolved()) { | 1523 if (!already_resolved()) { |
1518 num_stack_slots_ = 0; | 1524 num_stack_slots_ = 0; |
1519 } | 1525 } |
1520 // Allocate variables for inner scopes. | 1526 // Allocate variables for inner scopes. |
1521 for (int i = 0; i < inner_scopes_.length(); i++) { | 1527 for (int i = 0; i < inner_scopes_.length(); i++) { |
1522 inner_scopes_[i]->AllocateVariablesRecursively(isolate); | 1528 inner_scopes_[i]->AllocateVariablesRecursively(isolate); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1573 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1579 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1574 } | 1580 } |
1575 | 1581 |
1576 | 1582 |
1577 int Scope::ContextLocalCount() const { | 1583 int Scope::ContextLocalCount() const { |
1578 if (num_heap_slots() == 0) return 0; | 1584 if (num_heap_slots() == 0) return 0; |
1579 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1585 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1580 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1586 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1581 } | 1587 } |
1582 } } // namespace v8::internal | 1588 } } // namespace v8::internal |
OLD | NEW |