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 |
| 1158 Variable* Scope::ClassVariableForMethod() const { |
| 1159 if (!is_function_scope()) return nullptr; |
| 1160 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) && |
| 1161 !IsAccessorFunction(function_kind_)) { |
| 1162 return nullptr; |
| 1163 } |
| 1164 DCHECK_NOT_NULL(outer_scope_); |
| 1165 DCHECK(outer_scope_->is_class_scope()); |
| 1166 // The class scope contains at most one variable, the class name. |
| 1167 DCHECK(outer_scope_->variables_.occupancy() <= 1); |
| 1168 if (outer_scope_->variables_.occupancy() == 0) return nullptr; |
| 1169 VariableMap::Entry* p = outer_scope_->variables_.Start(); |
| 1170 return reinterpret_cast<Variable*>(p->value); |
| 1171 } |
| 1172 |
| 1173 |
1140 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, | 1174 bool Scope::ResolveVariablesRecursively(CompilationInfo* info, |
1141 AstNodeFactory* factory) { | 1175 AstNodeFactory* factory) { |
1142 DCHECK(info->script_scope()->is_script_scope()); | 1176 DCHECK(info->script_scope()->is_script_scope()); |
1143 | 1177 |
1144 // Resolve unresolved variables for this scope. | 1178 // Resolve unresolved variables for this scope. |
1145 for (int i = 0; i < unresolved_.length(); i++) { | 1179 for (int i = 0; i < unresolved_.length(); i++) { |
1146 if (!ResolveVariable(info, unresolved_[i], factory)) return false; | 1180 if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
1147 } | 1181 } |
1148 | 1182 |
1149 // Resolve unresolved variables for inner scopes. | 1183 // Resolve unresolved variables for inner scopes. |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1423 return num_stack_slots() - | 1457 return num_stack_slots() - |
1424 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1458 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1425 } | 1459 } |
1426 | 1460 |
1427 | 1461 |
1428 int Scope::ContextLocalCount() const { | 1462 int Scope::ContextLocalCount() const { |
1429 if (num_heap_slots() == 0) return 0; | 1463 if (num_heap_slots() == 0) return 0; |
1430 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1464 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1431 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1465 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1432 } | 1466 } |
1433 | |
1434 } } // namespace v8::internal | 1467 } } // namespace v8::internal |
OLD | NEW |