| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 } | 76 } |
| 77 Vector* delegates = static_cast<Vector*>(p->value); | 77 Vector* delegates = static_cast<Vector*>(p->value); |
| 78 delegates->push_back(stmt); | 78 delegates->push_back(stmt); |
| 79 } | 79 } |
| 80 | 80 |
| 81 | 81 |
| 82 // ---------------------------------------------------------------------------- | 82 // ---------------------------------------------------------------------------- |
| 83 // Implementation of Scope | 83 // Implementation of Scope |
| 84 | 84 |
| 85 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, | 85 Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type, |
| 86 AstValueFactory* ast_value_factory, FunctionKind function_kind) | 86 FunctionKind function_kind) |
| 87 : inner_scopes_(4, zone), | 87 : inner_scopes_(4, zone), |
| 88 variables_(zone), | 88 variables_(zone), |
| 89 temps_(4, zone), | 89 temps_(4, zone), |
| 90 params_(4, zone), | 90 params_(4, zone), |
| 91 unresolved_(nullptr), | 91 unresolved_(nullptr), |
| 92 decls_(4, zone), | 92 decls_(4, zone), |
| 93 module_descriptor_(scope_type == MODULE_SCOPE ? new (zone) | 93 module_descriptor_(scope_type == MODULE_SCOPE ? new (zone) |
| 94 ModuleDescriptor(zone) | 94 ModuleDescriptor(zone) |
| 95 : NULL), | 95 : NULL), |
| 96 sloppy_block_function_map_(zone), | 96 sloppy_block_function_map_(zone), |
| 97 already_resolved_(false), | 97 already_resolved_(false), |
| 98 ast_value_factory_(ast_value_factory), | |
| 99 zone_(zone) { | 98 zone_(zone) { |
| 100 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), | 99 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), |
| 101 function_kind); | 100 function_kind); |
| 102 // The outermost scope must be a script scope. | 101 // The outermost scope must be a script scope. |
| 103 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); | 102 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); |
| 104 } | 103 } |
| 105 | 104 |
| 106 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, | 105 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
| 107 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) | 106 Handle<ScopeInfo> scope_info) |
| 108 : inner_scopes_(4, zone), | 107 : inner_scopes_(4, zone), |
| 109 variables_(zone), | 108 variables_(zone), |
| 110 temps_(4, zone), | 109 temps_(4, zone), |
| 111 params_(4, zone), | 110 params_(4, zone), |
| 112 unresolved_(nullptr), | 111 unresolved_(nullptr), |
| 113 decls_(4, zone), | 112 decls_(4, zone), |
| 114 module_descriptor_(NULL), | 113 module_descriptor_(NULL), |
| 115 sloppy_block_function_map_(zone), | 114 sloppy_block_function_map_(zone), |
| 116 already_resolved_(true), | 115 already_resolved_(true), |
| 117 ast_value_factory_(value_factory), | |
| 118 zone_(zone) { | 116 zone_(zone) { |
| 119 SetDefaults(scope_type, NULL, scope_info); | 117 SetDefaults(scope_type, NULL, scope_info); |
| 120 if (!scope_info.is_null()) { | 118 if (!scope_info.is_null()) { |
| 121 num_heap_slots_ = scope_info_->ContextLength(); | 119 num_heap_slots_ = scope_info_->ContextLength(); |
| 122 } | 120 } |
| 123 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. | 121 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. |
| 124 num_heap_slots_ = Max(num_heap_slots_, | 122 num_heap_slots_ = Max(num_heap_slots_, |
| 125 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); | 123 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); |
| 126 AddInnerScope(inner_scope); | 124 AddInnerScope(inner_scope); |
| 127 } | 125 } |
| 128 | 126 |
| 129 Scope::Scope(Zone* zone, Scope* inner_scope, | 127 Scope::Scope(Zone* zone, Scope* inner_scope, |
| 130 const AstRawString* catch_variable_name, | 128 const AstRawString* catch_variable_name) |
| 131 AstValueFactory* value_factory) | |
| 132 : inner_scopes_(1, zone), | 129 : inner_scopes_(1, zone), |
| 133 variables_(zone), | 130 variables_(zone), |
| 134 temps_(0, zone), | 131 temps_(0, zone), |
| 135 params_(0, zone), | 132 params_(0, zone), |
| 136 unresolved_(nullptr), | 133 unresolved_(nullptr), |
| 137 decls_(0, zone), | 134 decls_(0, zone), |
| 138 module_descriptor_(NULL), | 135 module_descriptor_(NULL), |
| 139 sloppy_block_function_map_(zone), | 136 sloppy_block_function_map_(zone), |
| 140 already_resolved_(true), | 137 already_resolved_(true), |
| 141 ast_value_factory_(value_factory), | |
| 142 zone_(zone) { | 138 zone_(zone) { |
| 143 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); | 139 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
| 144 AddInnerScope(inner_scope); | 140 AddInnerScope(inner_scope); |
| 145 ++num_var_; | 141 ++num_var_; |
| 146 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 142 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 147 Variable* variable = variables_.Declare(this, | 143 Variable* variable = variables_.Declare(this, |
| 148 catch_variable_name, | 144 catch_variable_name, |
| 149 VAR, | 145 VAR, |
| 150 Variable::NORMAL, | 146 Variable::NORMAL, |
| 151 kCreatedInitialized); | 147 kCreatedInitialized); |
| 152 AllocateHeapSlot(variable); | 148 AllocateHeapSlot(variable); |
| 153 } | 149 } |
| 154 | 150 |
| 155 | 151 |
| 156 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, | 152 void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, |
| 157 Handle<ScopeInfo> scope_info, | 153 Handle<ScopeInfo> scope_info, |
| 158 FunctionKind function_kind) { | 154 FunctionKind function_kind) { |
| 159 outer_scope_ = outer_scope; | 155 outer_scope_ = outer_scope; |
| 160 scope_type_ = scope_type; | 156 scope_type_ = scope_type; |
| 161 is_declaration_scope_ = | 157 is_declaration_scope_ = |
| 162 is_eval_scope() || is_function_scope() || | 158 is_eval_scope() || is_function_scope() || |
| 163 is_module_scope() || is_script_scope(); | 159 is_module_scope() || is_script_scope(); |
| 164 function_kind_ = function_kind; | 160 function_kind_ = function_kind; |
| 165 scope_name_ = ast_value_factory_->empty_string(); | 161 scope_name_ = nullptr; |
| 166 dynamics_ = nullptr; | 162 dynamics_ = nullptr; |
| 167 receiver_ = nullptr; | 163 receiver_ = nullptr; |
| 168 new_target_ = nullptr; | 164 new_target_ = nullptr; |
| 169 function_ = nullptr; | 165 function_ = nullptr; |
| 170 arguments_ = nullptr; | 166 arguments_ = nullptr; |
| 171 this_function_ = nullptr; | 167 this_function_ = nullptr; |
| 172 scope_inside_with_ = false; | 168 scope_inside_with_ = false; |
| 173 scope_calls_eval_ = false; | 169 scope_calls_eval_ = false; |
| 174 scope_uses_arguments_ = false; | 170 scope_uses_arguments_ = false; |
| 175 scope_uses_super_property_ = false; | 171 scope_uses_super_property_ = false; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 199 end_position_ = kNoSourcePosition; | 195 end_position_ = kNoSourcePosition; |
| 200 is_hidden_ = false; | 196 is_hidden_ = false; |
| 201 if (!scope_info.is_null()) { | 197 if (!scope_info.is_null()) { |
| 202 scope_calls_eval_ = scope_info->CallsEval(); | 198 scope_calls_eval_ = scope_info->CallsEval(); |
| 203 language_mode_ = scope_info->language_mode(); | 199 language_mode_ = scope_info->language_mode(); |
| 204 is_declaration_scope_ = scope_info->is_declaration_scope(); | 200 is_declaration_scope_ = scope_info->is_declaration_scope(); |
| 205 function_kind_ = scope_info->function_kind(); | 201 function_kind_ = scope_info->function_kind(); |
| 206 } | 202 } |
| 207 } | 203 } |
| 208 | 204 |
| 209 | |
| 210 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 205 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
| 211 Context* context, Scope* script_scope) { | 206 Context* context, Scope* script_scope, |
| 207 AstValueFactory* ast_value_factory) { |
| 212 // Reconstruct the outer scope chain from a closure's context chain. | 208 // Reconstruct the outer scope chain from a closure's context chain. |
| 213 Scope* current_scope = NULL; | 209 Scope* current_scope = NULL; |
| 214 Scope* innermost_scope = NULL; | 210 Scope* innermost_scope = NULL; |
| 215 while (!context->IsNativeContext()) { | 211 while (!context->IsNativeContext()) { |
| 216 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { | 212 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { |
| 217 // For scope analysis, debug-evaluate is equivalent to a with scope. | 213 // For scope analysis, debug-evaluate is equivalent to a with scope. |
| 218 Scope* with_scope = new (zone) | 214 Scope* with_scope = new (zone) |
| 219 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null(), | 215 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null()); |
| 220 script_scope->ast_value_factory_); | |
| 221 current_scope = with_scope; | 216 current_scope = with_scope; |
| 222 // All the inner scopes are inside a with. | 217 // All the inner scopes are inside a with. |
| 223 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 218 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
| 224 s->scope_inside_with_ = true; | 219 s->scope_inside_with_ = true; |
| 225 } | 220 } |
| 226 } else if (context->IsScriptContext()) { | 221 } else if (context->IsScriptContext()) { |
| 227 ScopeInfo* scope_info = context->scope_info(); | 222 ScopeInfo* scope_info = context->scope_info(); |
| 228 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, | 223 current_scope = new (zone) Scope(zone, current_scope, SCRIPT_SCOPE, |
| 229 Handle<ScopeInfo>(scope_info), | 224 Handle<ScopeInfo>(scope_info)); |
| 230 script_scope->ast_value_factory_); | |
| 231 } else if (context->IsFunctionContext()) { | 225 } else if (context->IsFunctionContext()) { |
| 232 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); | 226 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
| 233 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE, | 227 current_scope = new (zone) Scope(zone, current_scope, FUNCTION_SCOPE, |
| 234 Handle<ScopeInfo>(scope_info), | 228 Handle<ScopeInfo>(scope_info)); |
| 235 script_scope->ast_value_factory_); | |
| 236 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; | 229 if (scope_info->IsAsmFunction()) current_scope->asm_function_ = true; |
| 237 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; | 230 if (scope_info->IsAsmModule()) current_scope->asm_module_ = true; |
| 238 } else if (context->IsBlockContext()) { | 231 } else if (context->IsBlockContext()) { |
| 239 ScopeInfo* scope_info = context->scope_info(); | 232 ScopeInfo* scope_info = context->scope_info(); |
| 240 current_scope = new (zone) | 233 current_scope = new (zone) Scope(zone, current_scope, BLOCK_SCOPE, |
| 241 Scope(zone, current_scope, BLOCK_SCOPE, Handle<ScopeInfo>(scope_info), | 234 Handle<ScopeInfo>(scope_info)); |
| 242 script_scope->ast_value_factory_); | |
| 243 } else { | 235 } else { |
| 244 DCHECK(context->IsCatchContext()); | 236 DCHECK(context->IsCatchContext()); |
| 245 String* name = context->catch_name(); | 237 String* name = context->catch_name(); |
| 246 current_scope = new (zone) Scope( | 238 current_scope = |
| 247 zone, current_scope, | 239 new (zone) Scope(zone, current_scope, |
| 248 script_scope->ast_value_factory_->GetString(Handle<String>(name)), | 240 ast_value_factory->GetString(handle(name, isolate))); |
| 249 script_scope->ast_value_factory_); | |
| 250 } | 241 } |
| 251 if (innermost_scope == NULL) innermost_scope = current_scope; | 242 if (innermost_scope == NULL) innermost_scope = current_scope; |
| 252 context = context->previous(); | 243 context = context->previous(); |
| 253 } | 244 } |
| 254 | 245 |
| 255 script_scope->AddInnerScope(current_scope); | 246 script_scope->AddInnerScope(current_scope); |
| 256 script_scope->PropagateScopeInfo(false); | 247 script_scope->PropagateScopeInfo(false); |
| 257 return (innermost_scope == NULL) ? script_scope : innermost_scope; | 248 return (innermost_scope == NULL) ? script_scope : innermost_scope; |
| 258 } | 249 } |
| 259 | 250 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 290 scope->CheckScopePositions(); | 281 scope->CheckScopePositions(); |
| 291 #endif | 282 #endif |
| 292 | 283 |
| 293 info->set_scope(scope); | 284 info->set_scope(scope); |
| 294 return true; | 285 return true; |
| 295 } | 286 } |
| 296 | 287 |
| 297 | 288 |
| 298 void Scope::Initialize() { | 289 void Scope::Initialize() { |
| 299 DCHECK(!already_resolved()); | 290 DCHECK(!already_resolved()); |
| 300 | 291 if (outer_scope_ == nullptr) { |
| 301 // Add this scope as a new inner scope of the outer scope. | 292 scope_inside_with_ = is_with_scope(); |
| 302 if (outer_scope_ != NULL) { | 293 } else { |
| 303 outer_scope_->inner_scopes_.Add(this, zone()); | 294 outer_scope_->inner_scopes_.Add(this, zone()); |
| 304 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); | 295 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); |
| 305 } else { | |
| 306 scope_inside_with_ = is_with_scope(); | |
| 307 } | |
| 308 | |
| 309 // Declare convenience variables and the receiver. | |
| 310 if (is_declaration_scope() && has_this_declaration()) { | |
| 311 bool subclass_constructor = IsSubclassConstructor(function_kind_); | |
| 312 Variable* var = variables_.Declare( | |
| 313 this, ast_value_factory_->this_string(), | |
| 314 subclass_constructor ? CONST : VAR, Variable::THIS, | |
| 315 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); | |
| 316 receiver_ = var; | |
| 317 } | |
| 318 | |
| 319 if (is_function_scope() && !is_arrow_scope()) { | |
| 320 // Declare 'arguments' variable which exists in all non arrow functions. | |
| 321 // Note that it might never be accessed, in which case it won't be | |
| 322 // allocated during variable allocation. | |
| 323 arguments_ = | |
| 324 variables_.Declare(this, ast_value_factory_->arguments_string(), VAR, | |
| 325 Variable::ARGUMENTS, kCreatedInitialized); | |
| 326 | |
| 327 new_target_ = | |
| 328 variables_.Declare(this, ast_value_factory_->new_target_string(), CONST, | |
| 329 Variable::NORMAL, kCreatedInitialized); | |
| 330 | |
| 331 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) || | |
| 332 IsAccessorFunction(function_kind_)) { | |
| 333 this_function_ = | |
| 334 variables_.Declare(this, ast_value_factory_->this_function_string(), | |
| 335 CONST, Variable::NORMAL, kCreatedInitialized); | |
| 336 } | |
| 337 } | 296 } |
| 338 } | 297 } |
| 339 | 298 |
| 299 void Scope::DeclareThis(AstValueFactory* ast_value_factory) { |
| 300 DCHECK(!already_resolved()); |
| 301 DCHECK(is_declaration_scope()); |
| 302 DCHECK(has_this_declaration()); |
| 303 |
| 304 bool subclass_constructor = IsSubclassConstructor(function_kind_); |
| 305 Variable* var = variables_.Declare( |
| 306 this, ast_value_factory->this_string(), |
| 307 subclass_constructor ? CONST : VAR, Variable::THIS, |
| 308 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); |
| 309 receiver_ = var; |
| 310 } |
| 311 |
| 312 void Scope::DeclareDefaultFunctionVariables( |
| 313 AstValueFactory* ast_value_factory) { |
| 314 DCHECK(is_function_scope()); |
| 315 DCHECK(!is_arrow_scope()); |
| 316 // Declare 'arguments' variable which exists in all non arrow functions. |
| 317 // Note that it might never be accessed, in which case it won't be |
| 318 // allocated during variable allocation. |
| 319 arguments_ = |
| 320 variables_.Declare(this, ast_value_factory->arguments_string(), VAR, |
| 321 Variable::ARGUMENTS, kCreatedInitialized); |
| 322 |
| 323 new_target_ = |
| 324 variables_.Declare(this, ast_value_factory->new_target_string(), CONST, |
| 325 Variable::NORMAL, kCreatedInitialized); |
| 326 |
| 327 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) || |
| 328 IsAccessorFunction(function_kind_)) { |
| 329 this_function_ = |
| 330 variables_.Declare(this, ast_value_factory->this_function_string(), |
| 331 CONST, Variable::NORMAL, kCreatedInitialized); |
| 332 } |
| 333 } |
| 334 |
| 340 | 335 |
| 341 Scope* Scope::FinalizeBlockScope() { | 336 Scope* Scope::FinalizeBlockScope() { |
| 342 DCHECK(is_block_scope()); | 337 DCHECK(is_block_scope()); |
| 343 DCHECK(temps_.is_empty()); | 338 DCHECK(temps_.is_empty()); |
| 344 DCHECK(params_.is_empty()); | 339 DCHECK(params_.is_empty()); |
| 345 | 340 |
| 346 if (num_var() > 0 || (is_declaration_scope() && calls_sloppy_eval())) { | 341 if (num_var() > 0 || (is_declaration_scope() && calls_sloppy_eval())) { |
| 347 return this; | 342 return this; |
| 348 } | 343 } |
| 349 | 344 |
| (...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 function_ != NULL && function_->proxy()->var()->IsContextSlot(); | 1546 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
| 1552 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1547 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1553 (is_function_var_in_context ? 1 : 0); | 1548 (is_function_var_in_context ? 1 : 0); |
| 1554 } | 1549 } |
| 1555 | 1550 |
| 1556 | 1551 |
| 1557 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1552 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1558 | 1553 |
| 1559 } // namespace internal | 1554 } // namespace internal |
| 1560 } // namespace v8 | 1555 } // namespace v8 |
| OLD | NEW |