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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 return reinterpret_cast<Variable*>(p->value); | 59 return reinterpret_cast<Variable*>(p->value); |
60 } | 60 } |
61 return NULL; | 61 return NULL; |
62 } | 62 } |
63 | 63 |
64 | 64 |
65 // ---------------------------------------------------------------------------- | 65 // ---------------------------------------------------------------------------- |
66 // Implementation of Scope | 66 // Implementation of Scope |
67 | 67 |
68 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, | 68 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, |
69 AstValueFactory* ast_value_factory) | 69 AstValueFactory* ast_value_factory, FunctionKind function_kind) |
70 : inner_scopes_(4, zone), | 70 : inner_scopes_(4, zone), |
71 variables_(zone), | 71 variables_(zone), |
72 internals_(4, zone), | 72 internals_(4, zone), |
73 temps_(4, zone), | 73 temps_(4, zone), |
74 params_(4, zone), | 74 params_(4, zone), |
75 unresolved_(16, zone), | 75 unresolved_(16, zone), |
76 decls_(4, zone), | 76 decls_(4, zone), |
77 module_descriptor_( | 77 module_descriptor_( |
78 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), | 78 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), |
79 already_resolved_(false), | 79 already_resolved_(false), |
80 ast_value_factory_(ast_value_factory), | 80 ast_value_factory_(ast_value_factory), |
81 zone_(zone) { | 81 zone_(zone) { |
82 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); | 82 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), |
83 function_kind); | |
83 // The outermost scope must be a script scope. | 84 // The outermost scope must be a script scope. |
84 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); | 85 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); |
85 DCHECK(!HasIllegalRedeclaration()); | 86 DCHECK(!HasIllegalRedeclaration()); |
86 } | 87 } |
87 | 88 |
88 | 89 |
89 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, | 90 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
90 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) | 91 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) |
91 : inner_scopes_(4, zone), | 92 : inner_scopes_(4, zone), |
92 variables_(zone), | 93 variables_(zone), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 Variable* variable = variables_.Declare(this, | 132 Variable* variable = variables_.Declare(this, |
132 catch_variable_name, | 133 catch_variable_name, |
133 VAR, | 134 VAR, |
134 true, // Valid left-hand side. | 135 true, // Valid left-hand side. |
135 Variable::NORMAL, | 136 Variable::NORMAL, |
136 kCreatedInitialized); | 137 kCreatedInitialized); |
137 AllocateHeapSlot(variable); | 138 AllocateHeapSlot(variable); |
138 } | 139 } |
139 | 140 |
140 | 141 |
141 void Scope::SetDefaults(ScopeType scope_type, | 142 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, |
142 Scope* outer_scope, | 143 Handle<ScopeInfo> scope_info, |
143 Handle<ScopeInfo> scope_info) { | 144 FunctionKind function_kind) { |
144 outer_scope_ = outer_scope; | 145 outer_scope_ = outer_scope; |
145 scope_type_ = scope_type; | 146 scope_type_ = scope_type; |
147 function_kind_ = function_kind; | |
148 block_scope_is_class_scope_ = false; | |
146 scope_name_ = ast_value_factory_->empty_string(); | 149 scope_name_ = ast_value_factory_->empty_string(); |
147 dynamics_ = NULL; | 150 dynamics_ = NULL; |
148 receiver_ = NULL; | 151 receiver_ = NULL; |
149 new_target_ = nullptr; | 152 new_target_ = nullptr; |
150 function_ = NULL; | 153 function_ = NULL; |
151 arguments_ = NULL; | 154 arguments_ = NULL; |
152 illegal_redecl_ = NULL; | 155 illegal_redecl_ = NULL; |
153 scope_inside_with_ = false; | 156 scope_inside_with_ = false; |
154 scope_contains_with_ = false; | 157 scope_contains_with_ = false; |
155 scope_calls_eval_ = false; | 158 scope_calls_eval_ = false; |
(...skipping 18 matching lines...) Expand all Loading... | |
174 num_modules_ = 0; | 177 num_modules_ = 0; |
175 module_var_ = NULL, | 178 module_var_ = NULL, |
176 rest_parameter_ = NULL; | 179 rest_parameter_ = NULL; |
177 rest_index_ = -1; | 180 rest_index_ = -1; |
178 scope_info_ = scope_info; | 181 scope_info_ = scope_info; |
179 start_position_ = RelocInfo::kNoPosition; | 182 start_position_ = RelocInfo::kNoPosition; |
180 end_position_ = RelocInfo::kNoPosition; | 183 end_position_ = RelocInfo::kNoPosition; |
181 if (!scope_info.is_null()) { | 184 if (!scope_info.is_null()) { |
182 scope_calls_eval_ = scope_info->CallsEval(); | 185 scope_calls_eval_ = scope_info->CallsEval(); |
183 language_mode_ = scope_info->language_mode(); | 186 language_mode_ = scope_info->language_mode(); |
187 block_scope_is_class_scope_ = scope_info->block_scope_is_class_scope(); | |
188 function_kind_ = scope_info->function_kind(); | |
184 } | 189 } |
185 } | 190 } |
186 | 191 |
187 | 192 |
188 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 193 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
189 Context* context, Scope* script_scope) { | 194 Context* context, Scope* script_scope) { |
190 // Reconstruct the outer scope chain from a closure's context chain. | 195 // Reconstruct the outer scope chain from a closure's context chain. |
191 Scope* current_scope = NULL; | 196 Scope* current_scope = NULL; |
192 Scope* innermost_scope = NULL; | 197 Scope* innermost_scope = NULL; |
193 bool contains_with = false; | 198 bool contains_with = false; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 : FLAG_print_scopes) { | 282 : FLAG_print_scopes) { |
278 scope->Print(); | 283 scope->Print(); |
279 } | 284 } |
280 #endif | 285 #endif |
281 | 286 |
282 info->PrepareForCompilation(scope); | 287 info->PrepareForCompilation(scope); |
283 return true; | 288 return true; |
284 } | 289 } |
285 | 290 |
286 | 291 |
287 void Scope::Initialize(bool subclass_constructor) { | 292 void Scope::Initialize() { |
293 bool subclass_constructor = IsSubclassConstructor(function_kind_); | |
288 DCHECK(!already_resolved()); | 294 DCHECK(!already_resolved()); |
289 | 295 |
290 // Add this scope as a new inner scope of the outer scope. | 296 // Add this scope as a new inner scope of the outer scope. |
291 if (outer_scope_ != NULL) { | 297 if (outer_scope_ != NULL) { |
292 outer_scope_->inner_scopes_.Add(this, zone()); | 298 outer_scope_->inner_scopes_.Add(this, zone()); |
293 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); | 299 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); |
294 } else { | 300 } else { |
295 scope_inside_with_ = is_with_scope(); | 301 scope_inside_with_ = is_with_scope(); |
296 } | 302 } |
297 | 303 |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1063 // (functions and consts may be resolved by the parser). | 1069 // (functions and consts may be resolved by the parser). |
1064 if (proxy->is_resolved()) return true; | 1070 if (proxy->is_resolved()) return true; |
1065 | 1071 |
1066 // Otherwise, try to resolve the variable. | 1072 // Otherwise, try to resolve the variable. |
1067 BindingKind binding_kind; | 1073 BindingKind binding_kind; |
1068 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1074 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
1069 switch (binding_kind) { | 1075 switch (binding_kind) { |
1070 case BOUND: | 1076 case BOUND: |
1071 // We found a variable binding. | 1077 // We found a variable binding. |
1072 if (is_strong(language_mode())) { | 1078 if (is_strong(language_mode())) { |
1073 // Check for declaration-after use (for variables) in strong mode. Note | 1079 if (!CheckStrongModeDeclaration(proxy, var)) return false; |
1074 // that we can only do this in the case where we have seen the | |
1075 // declaration. And we always allow referencing functions (for now). | |
1076 | |
1077 // If both the use and the declaration are inside an eval scope | |
1078 // (possibly indirectly), or one of them is, we need to check whether | |
1079 // they are inside the same eval scope or different | |
1080 // ones. | |
1081 | |
1082 // TODO(marja,rossberg): Detect errors across different evals (depends | |
1083 // on the future of eval in strong mode). | |
1084 const Scope* eval_for_use = NearestOuterEvalScope(); | |
1085 const Scope* eval_for_declaration = | |
1086 var->scope()->NearestOuterEvalScope(); | |
1087 | |
1088 if (proxy->position() != RelocInfo::kNoPosition && | |
1089 proxy->position() < var->initializer_position() && | |
1090 !var->is_function() && eval_for_use == eval_for_declaration) { | |
1091 DCHECK(proxy->end_position() != RelocInfo::kNoPosition); | |
1092 ReportMessage(proxy->position(), proxy->end_position(), | |
1093 "strong_use_before_declaration", proxy->raw_name()); | |
1094 return false; | |
1095 } | |
1096 } | 1080 } |
1097 break; | 1081 break; |
1098 | 1082 |
1099 case BOUND_EVAL_SHADOWED: | 1083 case BOUND_EVAL_SHADOWED: |
1100 // We either found a variable binding that might be shadowed by eval or | 1084 // We either found a variable binding that might be shadowed by eval or |
1101 // gave up on it (e.g. by encountering a local with the same in the outer | 1085 // gave up on it (e.g. by encountering a local with the same in the outer |
1102 // scope which was not promoted to a context, this can happen if we use | 1086 // scope which was not promoted to a context, this can happen if we use |
1103 // debugger to evaluate arbitrary expressions at a break point). | 1087 // debugger to evaluate arbitrary expressions at a break point). |
1104 if (var->IsGlobalObjectProperty()) { | 1088 if (var->IsGlobalObjectProperty()) { |
1105 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 1089 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
(...skipping 24 matching lines...) Expand all Loading... | |
1130 | 1114 |
1131 DCHECK(var != NULL); | 1115 DCHECK(var != NULL); |
1132 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1116 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1133 | 1117 |
1134 proxy->BindTo(var); | 1118 proxy->BindTo(var); |
1135 | 1119 |
1136 return true; | 1120 return true; |
1137 } | 1121 } |
1138 | 1122 |
1139 | 1123 |
1124 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { | |
1125 // Check for declaration-after use (for variables) in strong mode. Note that | |
1126 // we can only do this in the case where we have seen the declaration. And we | |
1127 // always allow referencing functions (for now). | |
1128 | |
1129 // Allow referencing the class name from methods of that class, even though | |
1130 // the initializer position for class names is only after the body. | |
1131 Scope* scope = this; | |
1132 while (scope) { | |
1133 if (scope->ClassVariableForMethod() == var) return true; | |
1134 scope = scope->outer_scope(); | |
1135 } | |
1136 | |
1137 // If both the use and the declaration are inside an eval scope (possibly | |
1138 // indirectly), or one of them is, we need to check whether they are inside | |
1139 // the same eval scope or different ones. | |
1140 | |
1141 // TODO(marja,rossberg): Detect errors across different evals (depends on the | |
1142 // future of eval in strong mode). | |
1143 const Scope* eval_for_use = NearestOuterEvalScope(); | |
1144 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); | |
1145 | |
1146 if (proxy->position() != RelocInfo::kNoPosition && | |
1147 proxy->position() < var->initializer_position() && !var->is_function() && | |
1148 eval_for_use == eval_for_declaration) { | |
1149 DCHECK(proxy->end_position() != RelocInfo::kNoPosition); | |
1150 ReportMessage(proxy->position(), proxy->end_position(), | |
1151 "strong_use_before_declaration", proxy->raw_name()); | |
1152 return false; | |
1153 } | |
1154 return true; | |
1155 } | |
1156 | |
1157 | |
1140 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, | 1158 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, |
1141 AstNodeFactory* factory) { | 1159 AstNodeFactory* factory) { |
1142 DCHECK(info->script_scope()->is_script_scope()); | 1160 DCHECK(info->script_scope()->is_script_scope()); |
1143 | 1161 |
1144 // Resolve unresolved variables for this scope. | 1162 // Resolve unresolved variables for this scope. |
1145 for (int i = 0; i < unresolved_.length(); i++) { | 1163 for (int i = 0; i < unresolved_.length(); i++) { |
1146 if (!ResolveVariable(info, unresolved_[i], factory)) return false; | 1164 if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
1147 } | 1165 } |
1148 | 1166 |
1149 // Resolve unresolved variables for inner scopes. | 1167 // Resolve unresolved variables for inner scopes. |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1424 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1442 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1425 } | 1443 } |
1426 | 1444 |
1427 | 1445 |
1428 int Scope::ContextLocalCount() const { | 1446 int Scope::ContextLocalCount() const { |
1429 if (num_heap_slots() == 0) return 0; | 1447 if (num_heap_slots() == 0) return 0; |
1430 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1448 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1431 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1449 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1432 } | 1450 } |
1433 | 1451 |
1452 | |
1453 Variable* Scope::ClassVariableForMethod() const { | |
rossberg
2015/03/09 10:41:46
Nit: move this next to CheckStrongModeDeclaration
marja
2015/03/09 13:44:06
Done.
| |
1454 if (!is_function_scope()) return nullptr; | |
1455 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) && | |
1456 !IsAccessorFunction(function_kind_)) { | |
1457 return nullptr; | |
1458 } | |
1459 DCHECK_NOT_NULL(outer_scope_); | |
1460 DCHECK(outer_scope_->is_class_scope()); | |
1461 // The class scope contains at most one variable, the class name. | |
1462 DCHECK(outer_scope_->variables_.occupancy() <= 1); | |
1463 if (outer_scope_->variables_.occupancy() == 0) return nullptr; | |
1464 VariableMap::Entry* p = outer_scope_->variables_.Start(); | |
1465 return reinterpret_cast<Variable*>(p->value); | |
1466 } | |
1434 } } // namespace v8::internal | 1467 } } // namespace v8::internal |
OLD | NEW |