| 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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 decls_(0, zone), | 128 decls_(0, zone), |
| 129 scope_info_(scope_info), | 129 scope_info_(scope_info), |
| 130 scope_type_(scope_type) { | 130 scope_type_(scope_type) { |
| 131 SetDefaults(); | 131 SetDefaults(); |
| 132 #ifdef DEBUG | 132 #ifdef DEBUG |
| 133 already_resolved_ = true; | 133 already_resolved_ = true; |
| 134 #endif | 134 #endif |
| 135 if (scope_type == WITH_SCOPE) { | 135 if (scope_type == WITH_SCOPE) { |
| 136 DCHECK(scope_info.is_null()); | 136 DCHECK(scope_info.is_null()); |
| 137 } else { | 137 } else { |
| 138 scope_calls_eval_ = scope_info->CallsEval(); | 138 if (scope_info->CallsEval()) RecordEvalCall(); |
| 139 set_language_mode(scope_info->language_mode()); | 139 set_language_mode(scope_info->language_mode()); |
| 140 num_heap_slots_ = scope_info->ContextLength(); | 140 num_heap_slots_ = scope_info->ContextLength(); |
| 141 } | 141 } |
| 142 DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_); | 142 DCHECK_LE(Context::MIN_CONTEXT_SLOTS, num_heap_slots_); |
| 143 | 143 |
| 144 if (inner_scope != nullptr) AddInnerScope(inner_scope); | 144 if (inner_scope != nullptr) AddInnerScope(inner_scope); |
| 145 } | 145 } |
| 146 | 146 |
| 147 DeclarationScope::DeclarationScope(Zone* zone, Scope* inner_scope, | 147 DeclarationScope::DeclarationScope(Zone* zone, Scope* inner_scope, |
| 148 ScopeType scope_type, | 148 ScopeType scope_type, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 171 variables_.Declare(zone, this, catch_variable_name, VAR, Variable::NORMAL, | 171 variables_.Declare(zone, this, catch_variable_name, VAR, Variable::NORMAL, |
| 172 kCreatedInitialized); | 172 kCreatedInitialized); |
| 173 AllocateHeapSlot(variable); | 173 AllocateHeapSlot(variable); |
| 174 } | 174 } |
| 175 | 175 |
| 176 void DeclarationScope::SetDefaults() { | 176 void DeclarationScope::SetDefaults() { |
| 177 is_declaration_scope_ = true; | 177 is_declaration_scope_ = true; |
| 178 has_simple_parameters_ = true; | 178 has_simple_parameters_ = true; |
| 179 asm_module_ = false; | 179 asm_module_ = false; |
| 180 asm_function_ = false; | 180 asm_function_ = false; |
| 181 force_eager_compilation_ = false; |
| 181 has_arguments_parameter_ = false; | 182 has_arguments_parameter_ = false; |
| 182 receiver_ = nullptr; | 183 receiver_ = nullptr; |
| 183 new_target_ = nullptr; | 184 new_target_ = nullptr; |
| 184 function_ = nullptr; | 185 function_ = nullptr; |
| 185 arguments_ = nullptr; | 186 arguments_ = nullptr; |
| 186 this_function_ = nullptr; | 187 this_function_ = nullptr; |
| 187 arity_ = 0; | 188 arity_ = 0; |
| 188 rest_parameter_ = nullptr; | 189 rest_parameter_ = nullptr; |
| 189 rest_index_ = -1; | 190 rest_index_ = -1; |
| 190 } | 191 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 208 | 209 |
| 209 set_language_mode(SLOPPY); | 210 set_language_mode(SLOPPY); |
| 210 | 211 |
| 211 scope_calls_eval_ = false; | 212 scope_calls_eval_ = false; |
| 212 scope_uses_super_property_ = false; | 213 scope_uses_super_property_ = false; |
| 213 scope_nonlinear_ = false; | 214 scope_nonlinear_ = false; |
| 214 is_hidden_ = false; | 215 is_hidden_ = false; |
| 215 is_debug_evaluate_scope_ = false; | 216 is_debug_evaluate_scope_ = false; |
| 216 | 217 |
| 217 inner_scope_calls_eval_ = false; | 218 inner_scope_calls_eval_ = false; |
| 218 force_eager_compilation_ = false; | |
| 219 force_context_allocation_ = false; | 219 force_context_allocation_ = false; |
| 220 | 220 |
| 221 is_declaration_scope_ = false; | 221 is_declaration_scope_ = false; |
| 222 } | 222 } |
| 223 | 223 |
| 224 bool Scope::HasSimpleParameters() { | 224 bool Scope::HasSimpleParameters() { |
| 225 DeclarationScope* scope = GetClosureScope(); | 225 DeclarationScope* scope = GetClosureScope(); |
| 226 return !scope->is_function_scope() || scope->has_simple_parameters(); | 226 return !scope->is_function_scope() || scope->has_simple_parameters(); |
| 227 } | 227 } |
| 228 | 228 |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 | 870 |
| 871 // 3) Allocate variables. | 871 // 3) Allocate variables. |
| 872 AllocateVariablesRecursively(); | 872 AllocateVariablesRecursively(); |
| 873 } | 873 } |
| 874 | 874 |
| 875 | 875 |
| 876 bool Scope::AllowsLazyParsing() const { | 876 bool Scope::AllowsLazyParsing() const { |
| 877 // If we are inside a block scope, we must parse eagerly to find out how | 877 // If we are inside a block scope, we must parse eagerly to find out how |
| 878 // to allocate variables on the block scope. At this point, declarations may | 878 // to allocate variables on the block scope. At this point, declarations may |
| 879 // not have yet been parsed. | 879 // not have yet been parsed. |
| 880 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { | 880 for (const Scope* s = this; s != nullptr; s = s->outer_scope_) { |
| 881 if (scope->is_block_scope()) return false; | 881 if (s->is_block_scope()) return false; |
| 882 } | 882 } |
| 883 return AllowsLazyCompilation(); | 883 return true; |
| 884 } | 884 } |
| 885 | 885 |
| 886 bool DeclarationScope::AllowsLazyCompilation() const { |
| 887 return !force_eager_compilation_; |
| 888 } |
| 886 | 889 |
| 887 bool Scope::AllowsLazyCompilation() const { return !force_eager_compilation_; } | 890 bool DeclarationScope::AllowsLazyCompilationWithoutContext() const { |
| 888 | |
| 889 | |
| 890 bool Scope::AllowsLazyCompilationWithoutContext() const { | |
| 891 if (force_eager_compilation_) return false; | 891 if (force_eager_compilation_) return false; |
| 892 // Disallow lazy compilation without context if any outer scope needs a | 892 // Disallow lazy compilation without context if any outer scope needs a |
| 893 // context. | 893 // context. |
| 894 for (const Scope* scope = outer_scope_; scope != nullptr; | 894 for (const Scope* scope = outer_scope_; scope != nullptr; |
| 895 scope = scope->outer_scope_) { | 895 scope = scope->outer_scope_) { |
| 896 if (scope->NeedsContext()) return false; | 896 if (scope->NeedsContext()) return false; |
| 897 } | 897 } |
| 898 return true; | 898 return true; |
| 899 } | 899 } |
| 900 | 900 |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1461 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1461 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
| 1462 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); | 1462 stack = scope->FetchFreeVariables(max_outer_scope, info, stack); |
| 1463 } | 1463 } |
| 1464 | 1464 |
| 1465 return stack; | 1465 return stack; |
| 1466 } | 1466 } |
| 1467 | 1467 |
| 1468 void Scope::PropagateScopeInfo() { | 1468 void Scope::PropagateScopeInfo() { |
| 1469 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { | 1469 for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { |
| 1470 inner->PropagateScopeInfo(); | 1470 inner->PropagateScopeInfo(); |
| 1471 if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) { | |
| 1472 inner_scope_calls_eval_ = true; | |
| 1473 } | |
| 1474 if (inner->force_eager_compilation_) { | |
| 1475 force_eager_compilation_ = true; | |
| 1476 } | |
| 1477 if (IsAsmModule() && inner->is_function_scope()) { | 1471 if (IsAsmModule() && inner->is_function_scope()) { |
| 1478 inner->AsDeclarationScope()->set_asm_function(); | 1472 inner->AsDeclarationScope()->set_asm_function(); |
| 1479 } | 1473 } |
| 1480 } | 1474 } |
| 1481 } | 1475 } |
| 1482 | 1476 |
| 1483 | 1477 |
| 1484 bool Scope::MustAllocate(Variable* var) { | 1478 bool Scope::MustAllocate(Variable* var) { |
| 1485 DCHECK(var->location() != VariableLocation::MODULE); | 1479 DCHECK(var->location() != VariableLocation::MODULE); |
| 1486 // Give var a read/write use if there is a chance it might be accessed | 1480 // Give var a read/write use if there is a chance it might be accessed |
| 1487 // via an eval() call. This is only possible if the variable has a | 1481 // via an eval() call. This is only possible if the variable has a |
| 1488 // visible name. | 1482 // visible name. |
| 1489 if ((var->is_this() || !var->raw_name()->IsEmpty()) && | 1483 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
| 1490 (scope_calls_eval_ || inner_scope_calls_eval_ || is_catch_scope() || | 1484 (inner_scope_calls_eval_ || is_catch_scope() || is_script_scope())) { |
| 1491 is_script_scope())) { | |
| 1492 var->set_is_used(); | 1485 var->set_is_used(); |
| 1493 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1486 if (inner_scope_calls_eval_) var->set_maybe_assigned(); |
| 1494 } | 1487 } |
| 1495 DCHECK(!var->has_forced_context_allocation() || var->is_used()); | 1488 DCHECK(!var->has_forced_context_allocation() || var->is_used()); |
| 1496 // Global variables do not need to be allocated. | 1489 // Global variables do not need to be allocated. |
| 1497 return !var->IsGlobalObjectProperty() && var->is_used(); | 1490 return !var->IsGlobalObjectProperty() && var->is_used(); |
| 1498 } | 1491 } |
| 1499 | 1492 |
| 1500 | 1493 |
| 1501 bool Scope::MustAllocateInContext(Variable* var) { | 1494 bool Scope::MustAllocateInContext(Variable* var) { |
| 1502 // If var is accessed from an inner scope, or if there is a possibility | 1495 // If var is accessed from an inner scope, or if there is a possibility |
| 1503 // that it might be accessed from the current or an inner scope (through | 1496 // that it might be accessed from the current or an inner scope (through |
| 1504 // an eval() call or a runtime with lookup), it must be allocated in the | 1497 // an eval() call or a runtime with lookup), it must be allocated in the |
| 1505 // context. | 1498 // context. |
| 1506 // | 1499 // |
| 1507 // Exceptions: If the scope as a whole has forced context allocation, all | 1500 // Exceptions: If the scope as a whole has forced context allocation, all |
| 1508 // variables will have context allocation, even temporaries. Otherwise | 1501 // variables will have context allocation, even temporaries. Otherwise |
| 1509 // temporary variables are always stack-allocated. Catch-bound variables are | 1502 // temporary variables are always stack-allocated. Catch-bound variables are |
| 1510 // always context-allocated. | 1503 // always context-allocated. |
| 1511 if (has_forced_context_allocation()) return true; | 1504 if (has_forced_context_allocation()) return true; |
| 1512 if (var->mode() == TEMPORARY) return false; | 1505 if (var->mode() == TEMPORARY) return false; |
| 1513 if (is_catch_scope()) return true; | 1506 if (is_catch_scope()) return true; |
| 1514 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; | 1507 if (is_script_scope() && IsLexicalVariableMode(var->mode())) return true; |
| 1515 return var->has_forced_context_allocation() || scope_calls_eval_ || | 1508 return var->has_forced_context_allocation() || inner_scope_calls_eval_; |
| 1516 inner_scope_calls_eval_; | |
| 1517 } | 1509 } |
| 1518 | 1510 |
| 1519 | 1511 |
| 1520 void Scope::AllocateStackSlot(Variable* var) { | 1512 void Scope::AllocateStackSlot(Variable* var) { |
| 1521 if (is_block_scope()) { | 1513 if (is_block_scope()) { |
| 1522 outer_scope()->GetDeclarationScope()->AllocateStackSlot(var); | 1514 outer_scope()->GetDeclarationScope()->AllocateStackSlot(var); |
| 1523 } else { | 1515 } else { |
| 1524 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); | 1516 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); |
| 1525 } | 1517 } |
| 1526 } | 1518 } |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1761 function != nullptr && function->IsContextSlot(); | 1753 function != nullptr && function->IsContextSlot(); |
| 1762 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1754 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1763 (is_function_var_in_context ? 1 : 0); | 1755 (is_function_var_in_context ? 1 : 0); |
| 1764 } | 1756 } |
| 1765 | 1757 |
| 1766 | 1758 |
| 1767 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1759 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1768 | 1760 |
| 1769 } // namespace internal | 1761 } // namespace internal |
| 1770 } // namespace v8 | 1762 } // namespace v8 |
| OLD | NEW |