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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 scope_inside_with_ = false; | 172 scope_inside_with_ = false; |
173 scope_calls_eval_ = false; | 173 scope_calls_eval_ = false; |
174 scope_uses_arguments_ = false; | 174 scope_uses_arguments_ = false; |
175 has_arguments_parameter_ = false; | |
175 scope_uses_super_property_ = false; | 176 scope_uses_super_property_ = false; |
176 asm_module_ = false; | 177 asm_module_ = false; |
177 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; | 178 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; |
178 // Inherit the language mode from the parent scope. | 179 // Inherit the language mode from the parent scope. |
179 language_mode_ = | 180 language_mode_ = |
180 is_module_scope() | 181 is_module_scope() |
181 ? STRICT | 182 ? STRICT |
182 : (outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY); | 183 : (outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY); |
183 outer_scope_calls_sloppy_eval_ = false; | 184 outer_scope_calls_sloppy_eval_ = false; |
184 inner_scope_calls_eval_ = false; | 185 inner_scope_calls_eval_ = false; |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
501 } | 502 } |
502 if (!is_optional && !is_rest && arity_ == params_.length()) { | 503 if (!is_optional && !is_rest && arity_ == params_.length()) { |
503 ++arity_; | 504 ++arity_; |
504 } | 505 } |
505 if (is_rest) { | 506 if (is_rest) { |
506 DCHECK_NULL(rest_parameter_); | 507 DCHECK_NULL(rest_parameter_); |
507 rest_parameter_ = var; | 508 rest_parameter_ = var; |
508 rest_index_ = num_parameters(); | 509 rest_index_ = num_parameters(); |
509 } | 510 } |
510 params_.Add(var, zone()); | 511 params_.Add(var, zone()); |
512 if (name == ast_value_factory_->arguments_string()) { | |
513 has_arguments_parameter_ = true; | |
514 } | |
511 return var; | 515 return var; |
512 } | 516 } |
513 | 517 |
514 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 518 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
515 InitializationFlag init_flag, Variable::Kind kind, | 519 InitializationFlag init_flag, Variable::Kind kind, |
516 MaybeAssignedFlag maybe_assigned_flag) { | 520 MaybeAssignedFlag maybe_assigned_flag) { |
517 DCHECK(!already_resolved()); | 521 DCHECK(!already_resolved()); |
518 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 522 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
519 // introduced during variable allocation, and TEMPORARY variables are | 523 // introduced during variable allocation, and TEMPORARY variables are |
520 // allocated via NewTemporary(). | 524 // allocated via NewTemporary(). |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
715 outer_scope_calls_sloppy_eval = | 719 outer_scope_calls_sloppy_eval = |
716 outer_scope_->outer_scope_calls_sloppy_eval() | | 720 outer_scope_->outer_scope_calls_sloppy_eval() | |
717 outer_scope_->calls_sloppy_eval(); | 721 outer_scope_->calls_sloppy_eval(); |
718 } | 722 } |
719 PropagateScopeInfo(outer_scope_calls_sloppy_eval); | 723 PropagateScopeInfo(outer_scope_calls_sloppy_eval); |
720 | 724 |
721 // 2) Resolve variables. | 725 // 2) Resolve variables. |
722 if (!ResolveVariablesRecursively(info, factory)) return false; | 726 if (!ResolveVariablesRecursively(info, factory)) return false; |
723 | 727 |
724 // 3) Allocate variables. | 728 // 3) Allocate variables. |
725 AllocateVariablesRecursively(info->isolate()); | 729 AllocateVariablesRecursively(); |
726 | 730 |
727 return true; | 731 return true; |
728 } | 732 } |
729 | 733 |
730 | 734 |
731 bool Scope::HasTrivialContext() const { | 735 bool Scope::HasTrivialContext() const { |
732 // A function scope has a trivial context if it always is the global | 736 // A function scope has a trivial context if it always is the global |
733 // context. We iteratively scan out the context chain to see if | 737 // context. We iteratively scan out the context chain to see if |
734 // there is anything that makes this scope non-trivial; otherwise we | 738 // there is anything that makes this scope non-trivial; otherwise we |
735 // return true. | 739 // return true. |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1298 // always context-allocated. | 1302 // always context-allocated. |
1299 if (has_forced_context_allocation()) return true; | 1303 if (has_forced_context_allocation()) return true; |
1300 if (var->mode() == TEMPORARY) return false; | 1304 if (var->mode() == TEMPORARY) return false; |
1301 if (is_catch_scope() || is_module_scope()) return true; | 1305 if (is_catch_scope() || is_module_scope()) return true; |
1302 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; | 1306 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; |
1303 return var->has_forced_context_allocation() || scope_calls_eval_ || | 1307 return var->has_forced_context_allocation() || scope_calls_eval_ || |
1304 inner_scope_calls_eval_; | 1308 inner_scope_calls_eval_; |
1305 } | 1309 } |
1306 | 1310 |
1307 | 1311 |
1308 bool Scope::HasArgumentsParameter(Isolate* isolate) { | |
1309 for (int i = 0; i < params_.length(); i++) { | |
1310 if (params_[i]->name().is_identical_to( | |
1311 isolate->factory()->arguments_string())) { | |
1312 return true; | |
1313 } | |
1314 } | |
1315 return false; | |
1316 } | |
1317 | |
1318 | |
1319 void Scope::AllocateStackSlot(Variable* var) { | 1312 void Scope::AllocateStackSlot(Variable* var) { |
1320 if (is_block_scope()) { | 1313 if (is_block_scope()) { |
1321 outer_scope()->DeclarationScope()->AllocateStackSlot(var); | 1314 outer_scope()->DeclarationScope()->AllocateStackSlot(var); |
1322 } else { | 1315 } else { |
1323 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); | 1316 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); |
1324 } | 1317 } |
1325 } | 1318 } |
1326 | 1319 |
1327 | 1320 |
1328 void Scope::AllocateHeapSlot(Variable* var) { | 1321 void Scope::AllocateHeapSlot(Variable* var) { |
1329 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++); | 1322 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++); |
1330 } | 1323 } |
1331 | 1324 |
1332 | 1325 void Scope::AllocateParameterLocals() { |
1333 void Scope::AllocateParameterLocals(Isolate* isolate) { | |
1334 DCHECK(is_function_scope()); | 1326 DCHECK(is_function_scope()); |
1335 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); | 1327 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); |
1336 // Functions have 'arguments' declared implicitly in all non arrow functions. | 1328 // Functions have 'arguments' declared implicitly in all non arrow functions. |
1337 DCHECK(arguments != nullptr || is_arrow_scope()); | 1329 DCHECK(arguments != nullptr || is_arrow_scope()); |
1338 | 1330 |
1339 bool uses_sloppy_arguments = false; | 1331 bool uses_sloppy_arguments = false; |
1340 | 1332 |
1341 if (arguments != nullptr && MustAllocate(arguments) && | 1333 if (arguments != nullptr && MustAllocate(arguments) && |
1342 !HasArgumentsParameter(isolate)) { | 1334 !has_arguments_parameter_) { |
1343 // 'arguments' is used. Unless there is also a parameter called | 1335 // 'arguments' is used. Unless there is also a parameter called |
1344 // 'arguments', we must be conservative and allocate all parameters to | 1336 // 'arguments', we must be conservative and allocate all parameters to |
1345 // the context assuming they will be captured by the arguments object. | 1337 // the context assuming they will be captured by the arguments object. |
1346 // If we have a parameter named 'arguments', a (new) value is always | 1338 // If we have a parameter named 'arguments', a (new) value is always |
1347 // assigned to it via the function invocation. Then 'arguments' denotes | 1339 // assigned to it via the function invocation. Then 'arguments' denotes |
1348 // that specific parameter value and cannot be used to access the | 1340 // that specific parameter value and cannot be used to access the |
1349 // parameters, which is why we don't need to allocate an arguments | 1341 // parameters, which is why we don't need to allocate an arguments |
1350 // object in that case. | 1342 // object in that case. |
1351 | 1343 |
1352 // We are using 'arguments'. Tell the code generator that is needs to | 1344 // We are using 'arguments'. Tell the code generator that is needs to |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1406 DCHECK_NOT_NULL(receiver()); | 1398 DCHECK_NOT_NULL(receiver()); |
1407 DCHECK_EQ(receiver()->scope(), this); | 1399 DCHECK_EQ(receiver()->scope(), this); |
1408 | 1400 |
1409 if (has_forced_context_allocation()) { | 1401 if (has_forced_context_allocation()) { |
1410 // Force context allocation of the receiver. | 1402 // Force context allocation of the receiver. |
1411 receiver()->ForceContextAllocation(); | 1403 receiver()->ForceContextAllocation(); |
1412 } | 1404 } |
1413 AllocateParameter(receiver(), -1); | 1405 AllocateParameter(receiver(), -1); |
1414 } | 1406 } |
1415 | 1407 |
1416 | 1408 void Scope::AllocateNonParameterLocal(Variable* var) { |
1417 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) { | |
1418 DCHECK(var->scope() == this); | 1409 DCHECK(var->scope() == this); |
1419 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || | 1410 // DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
1420 !var->IsStackLocal()); | 1411 // !var->IsStackLocal()); |
Toon Verwaest
2016/07/19 11:49:42
We shouldn't leave old code around in comments. Ei
marja
2016/07/19 11:53:08
Oops, this was unintentional, will fix
| |
1421 if (var->IsUnallocated() && MustAllocate(var)) { | 1412 if (var->IsUnallocated() && MustAllocate(var)) { |
1422 if (MustAllocateInContext(var)) { | 1413 if (MustAllocateInContext(var)) { |
1423 AllocateHeapSlot(var); | 1414 AllocateHeapSlot(var); |
1424 } else { | 1415 } else { |
1425 AllocateStackSlot(var); | 1416 AllocateStackSlot(var); |
1426 } | 1417 } |
1427 } | 1418 } |
1428 } | 1419 } |
1429 | 1420 |
1430 | 1421 void Scope::AllocateDeclaredGlobal(Variable* var) { |
1431 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) { | |
1432 DCHECK(var->scope() == this); | 1422 DCHECK(var->scope() == this); |
1433 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || | 1423 // DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
1434 !var->IsStackLocal()); | 1424 // !var->IsStackLocal()); |
1435 if (var->IsUnallocated()) { | 1425 if (var->IsUnallocated()) { |
1436 if (var->IsStaticGlobalObjectProperty()) { | 1426 if (var->IsStaticGlobalObjectProperty()) { |
1437 DCHECK_EQ(-1, var->index()); | 1427 DCHECK_EQ(-1, var->index()); |
1438 DCHECK(var->name()->IsString()); | 1428 DCHECK(var->name()->IsString()); |
1439 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_++); | 1429 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_++); |
1440 num_global_slots_++; | 1430 num_global_slots_++; |
1441 } else { | 1431 } else { |
1442 // There must be only DYNAMIC_GLOBAL in the script scope. | 1432 // There must be only DYNAMIC_GLOBAL in the script scope. |
1443 DCHECK(!is_script_scope() || DYNAMIC_GLOBAL == var->mode()); | 1433 DCHECK(!is_script_scope() || DYNAMIC_GLOBAL == var->mode()); |
1444 } | 1434 } |
1445 } | 1435 } |
1446 } | 1436 } |
1447 | 1437 |
1448 | 1438 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals() { |
1449 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) { | |
1450 // All variables that have no rewrite yet are non-parameter locals. | 1439 // All variables that have no rewrite yet are non-parameter locals. |
1451 for (int i = 0; i < temps_.length(); i++) { | 1440 for (int i = 0; i < temps_.length(); i++) { |
1452 if (temps_[i] == nullptr) continue; | 1441 if (temps_[i] == nullptr) continue; |
1453 AllocateNonParameterLocal(isolate, temps_[i]); | 1442 AllocateNonParameterLocal(temps_[i]); |
1454 } | 1443 } |
1455 | 1444 |
1456 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); | 1445 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
1457 for (VariableMap::Entry* p = variables_.Start(); | 1446 for (VariableMap::Entry* p = variables_.Start(); |
1458 p != NULL; | 1447 p != NULL; |
1459 p = variables_.Next(p)) { | 1448 p = variables_.Next(p)) { |
1460 Variable* var = reinterpret_cast<Variable*>(p->value); | 1449 Variable* var = reinterpret_cast<Variable*>(p->value); |
1461 vars.Add(VarAndOrder(var, p->order), zone()); | 1450 vars.Add(VarAndOrder(var, p->order), zone()); |
1462 } | 1451 } |
1463 vars.Sort(VarAndOrder::Compare); | 1452 vars.Sort(VarAndOrder::Compare); |
1464 int var_count = vars.length(); | 1453 int var_count = vars.length(); |
1465 for (int i = 0; i < var_count; i++) { | 1454 for (int i = 0; i < var_count; i++) { |
1466 AllocateNonParameterLocal(isolate, vars[i].var()); | 1455 AllocateNonParameterLocal(vars[i].var()); |
1467 } | 1456 } |
1468 | 1457 |
1469 if (FLAG_global_var_shortcuts) { | 1458 if (FLAG_global_var_shortcuts) { |
1470 for (int i = 0; i < var_count; i++) { | 1459 for (int i = 0; i < var_count; i++) { |
1471 AllocateDeclaredGlobal(isolate, vars[i].var()); | 1460 AllocateDeclaredGlobal(vars[i].var()); |
1472 } | 1461 } |
1473 } | 1462 } |
1474 | 1463 |
1475 // For now, function_ must be allocated at the very end. If it gets | 1464 // For now, function_ must be allocated at the very end. If it gets |
1476 // allocated in the context, it must be the last slot in the context, | 1465 // allocated in the context, it must be the last slot in the context, |
1477 // because of the current ScopeInfo implementation (see | 1466 // because of the current ScopeInfo implementation (see |
1478 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1467 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
1479 if (function_ != nullptr) { | 1468 if (function_ != nullptr) { |
1480 AllocateNonParameterLocal(isolate, function_->proxy()->var()); | 1469 AllocateNonParameterLocal(function_->proxy()->var()); |
1481 } | 1470 } |
1482 | 1471 |
1483 if (rest_parameter_ != nullptr) { | 1472 if (rest_parameter_ != nullptr) { |
1484 AllocateNonParameterLocal(isolate, rest_parameter_); | 1473 AllocateNonParameterLocal(rest_parameter_); |
1485 } | 1474 } |
1486 | 1475 |
1487 Variable* new_target_var = | 1476 Variable* new_target_var = |
1488 LookupLocal(ast_value_factory_->new_target_string()); | 1477 LookupLocal(ast_value_factory_->new_target_string()); |
1489 if (new_target_var != nullptr && MustAllocate(new_target_var)) { | 1478 if (new_target_var != nullptr && MustAllocate(new_target_var)) { |
1490 new_target_ = new_target_var; | 1479 new_target_ = new_target_var; |
1491 } | 1480 } |
1492 | 1481 |
1493 Variable* this_function_var = | 1482 Variable* this_function_var = |
1494 LookupLocal(ast_value_factory_->this_function_string()); | 1483 LookupLocal(ast_value_factory_->this_function_string()); |
1495 if (this_function_var != nullptr && MustAllocate(this_function_var)) { | 1484 if (this_function_var != nullptr && MustAllocate(this_function_var)) { |
1496 this_function_ = this_function_var; | 1485 this_function_ = this_function_var; |
1497 } | 1486 } |
1498 } | 1487 } |
1499 | 1488 |
1500 | 1489 void Scope::AllocateVariablesRecursively() { |
1501 void Scope::AllocateVariablesRecursively(Isolate* isolate) { | |
1502 if (!already_resolved()) { | 1490 if (!already_resolved()) { |
1503 num_stack_slots_ = 0; | 1491 num_stack_slots_ = 0; |
1504 } | 1492 } |
1505 // Allocate variables for inner scopes. | 1493 // Allocate variables for inner scopes. |
1506 for (int i = 0; i < inner_scopes_.length(); i++) { | 1494 for (int i = 0; i < inner_scopes_.length(); i++) { |
1507 inner_scopes_[i]->AllocateVariablesRecursively(isolate); | 1495 inner_scopes_[i]->AllocateVariablesRecursively(); |
1508 } | 1496 } |
1509 | 1497 |
1510 // If scope is already resolved, we still need to allocate | 1498 // If scope is already resolved, we still need to allocate |
1511 // variables in inner scopes which might not have been resolved yet. | 1499 // variables in inner scopes which might not have been resolved yet. |
1512 if (already_resolved()) return; | 1500 if (already_resolved()) return; |
1513 // The number of slots required for variables. | 1501 // The number of slots required for variables. |
1514 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1502 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
1515 | 1503 |
1516 // Allocate variables for this scope. | 1504 // Allocate variables for this scope. |
1517 // Parameters must be allocated first, if any. | 1505 // Parameters must be allocated first, if any. |
1518 if (is_function_scope()) AllocateParameterLocals(isolate); | 1506 if (is_function_scope()) AllocateParameterLocals(); |
1519 if (has_this_declaration()) AllocateReceiver(); | 1507 if (has_this_declaration()) AllocateReceiver(); |
1520 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); | 1508 AllocateNonParameterLocalsAndDeclaredGlobals(); |
1521 | 1509 |
1522 // Force allocation of a context for this scope if necessary. For a 'with' | 1510 // Force allocation of a context for this scope if necessary. For a 'with' |
1523 // scope and for a function scope that makes an 'eval' call we need a context, | 1511 // scope and for a function scope that makes an 'eval' call we need a context, |
1524 // even if no local variables were statically allocated in the scope. | 1512 // even if no local variables were statically allocated in the scope. |
1525 // Likewise for modules. | 1513 // Likewise for modules. |
1526 bool must_have_context = | 1514 bool must_have_context = |
1527 is_with_scope() || is_module_scope() || | 1515 is_with_scope() || is_module_scope() || |
1528 (is_function_scope() && calls_sloppy_eval()) || | 1516 (is_function_scope() && calls_sloppy_eval()) || |
1529 (is_block_scope() && is_declaration_scope() && calls_sloppy_eval()); | 1517 (is_block_scope() && is_declaration_scope() && calls_sloppy_eval()); |
1530 | 1518 |
(...skipping 20 matching lines...) Expand all Loading... | |
1551 function_ != NULL && function_->proxy()->var()->IsContextSlot(); | 1539 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
1552 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1540 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1553 (is_function_var_in_context ? 1 : 0); | 1541 (is_function_var_in_context ? 1 : 0); |
1554 } | 1542 } |
1555 | 1543 |
1556 | 1544 |
1557 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1545 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1558 | 1546 |
1559 } // namespace internal | 1547 } // namespace internal |
1560 } // namespace v8 | 1548 } // namespace v8 |
OLD | NEW |