| 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/ast/ast.h" | 10 #include "src/ast/ast.h" |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 | 301 |
| 302 bool Scope::IsAsmModule() const { | 302 bool Scope::IsAsmModule() const { |
| 303 return is_function_scope() && AsDeclarationScope()->asm_module(); | 303 return is_function_scope() && AsDeclarationScope()->asm_module(); |
| 304 } | 304 } |
| 305 | 305 |
| 306 bool Scope::IsAsmFunction() const { | 306 bool Scope::IsAsmFunction() const { |
| 307 return is_function_scope() && AsDeclarationScope()->asm_function(); | 307 return is_function_scope() && AsDeclarationScope()->asm_function(); |
| 308 } | 308 } |
| 309 | 309 |
| 310 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 310 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
| 311 Context* context, | 311 ScopeInfo* scope_info, |
| 312 DeclarationScope* script_scope, | 312 DeclarationScope* script_scope, |
| 313 AstValueFactory* ast_value_factory, | 313 AstValueFactory* ast_value_factory, |
| 314 DeserializationMode deserialization_mode) { | 314 DeserializationMode deserialization_mode) { |
| 315 // Reconstruct the outer scope chain from a closure's context chain. | 315 // Reconstruct the outer scope chain from a closure's context chain. |
| 316 Scope* current_scope = nullptr; | 316 Scope* current_scope = nullptr; |
| 317 Scope* innermost_scope = nullptr; | 317 Scope* innermost_scope = nullptr; |
| 318 Scope* outer_scope = nullptr; | 318 Scope* outer_scope = nullptr; |
| 319 while (!context->IsNativeContext()) { | 319 while (scope_info) { |
| 320 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { | 320 if (scope_info->scope_type() == WITH_SCOPE) { |
| 321 // For scope analysis, debug-evaluate is equivalent to a with scope. | 321 // For scope analysis, debug-evaluate is equivalent to a with scope. |
| 322 outer_scope = new (zone) | 322 outer_scope = new (zone) Scope(zone, WITH_SCOPE, handle(scope_info)); |
| 323 Scope(zone, WITH_SCOPE, Handle<ScopeInfo>(context->scope_info())); | |
| 324 | 323 |
| 325 // TODO(yangguo): Remove once debug-evaluate properly keeps track of the | 324 // TODO(yangguo): Remove once debug-evaluate properly keeps track of the |
| 326 // function scope in which we are evaluating. | 325 // function scope in which we are evaluating. |
| 327 if (context->IsDebugEvaluateContext()) { | 326 if (scope_info->IsDebugEvaluateScope()) { |
| 328 outer_scope->set_is_debug_evaluate_scope(); | 327 outer_scope->set_is_debug_evaluate_scope(); |
| 329 } | 328 } |
| 330 } else if (context->IsScriptContext()) { | 329 } else if (scope_info->scope_type() == SCRIPT_SCOPE) { |
| 331 // If we reach a script context, it's the outermost context with scope | 330 // If we reach a script scope, it's the outermost scope. Install the |
| 332 // info. The next context will be the native context. Install the scope | 331 // scope info of this script context onto the existing script scope to |
| 333 // info of this script context onto the existing script scope to avoid | 332 // avoid nesting script scopes. |
| 334 // nesting script scopes. | |
| 335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | |
| 336 if (deserialization_mode == DeserializationMode::kIncludingVariables) { | 333 if (deserialization_mode == DeserializationMode::kIncludingVariables) { |
| 337 script_scope->SetScriptScopeInfo(scope_info); | 334 script_scope->SetScriptScopeInfo(handle(scope_info)); |
| 338 } | 335 } |
| 339 DCHECK(context->previous()->IsNativeContext()); | 336 DCHECK(!scope_info->HasOuterScopeInfo()); |
| 340 break; | 337 break; |
| 341 } else if (context->IsFunctionContext()) { | 338 } else if (scope_info->scope_type() == FUNCTION_SCOPE || |
| 342 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 339 scope_info->scope_type() == EVAL_SCOPE) { |
| 343 // TODO(neis): For an eval scope, we currently create an ordinary function | 340 // TODO(neis): For an eval scope, we currently create an ordinary function |
| 344 // context. This is wrong and needs to be fixed. | 341 // context. This is wrong and needs to be fixed. |
| 345 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 342 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
| 346 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | |
| 347 scope_info->scope_type() == EVAL_SCOPE); | |
| 348 outer_scope = | 343 outer_scope = |
| 349 new (zone) DeclarationScope(zone, FUNCTION_SCOPE, scope_info); | 344 new (zone) DeclarationScope(zone, FUNCTION_SCOPE, handle(scope_info)); |
| 350 if (scope_info->IsAsmFunction()) | 345 if (scope_info->IsAsmFunction()) |
| 351 outer_scope->AsDeclarationScope()->set_asm_function(); | 346 outer_scope->AsDeclarationScope()->set_asm_function(); |
| 352 if (scope_info->IsAsmModule()) | 347 if (scope_info->IsAsmModule()) |
| 353 outer_scope->AsDeclarationScope()->set_asm_module(); | 348 outer_scope->AsDeclarationScope()->set_asm_module(); |
| 354 } else if (context->IsBlockContext()) { | 349 } else if (scope_info->scope_type() == BLOCK_SCOPE) { |
| 355 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | |
| 356 DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE); | |
| 357 if (scope_info->is_declaration_scope()) { | 350 if (scope_info->is_declaration_scope()) { |
| 358 outer_scope = | 351 outer_scope = |
| 359 new (zone) DeclarationScope(zone, BLOCK_SCOPE, scope_info); | 352 new (zone) DeclarationScope(zone, BLOCK_SCOPE, handle(scope_info)); |
| 360 } else { | 353 } else { |
| 361 outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, scope_info); | 354 outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, handle(scope_info)); |
| 362 } | 355 } |
| 363 } else if (context->IsModuleContext()) { | 356 } else if (scope_info->scope_type() == MODULE_SCOPE) { |
| 364 ScopeInfo* scope_info = context->scope_info(); | 357 outer_scope = new (zone) |
| 365 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); | 358 ModuleScope(isolate, handle(scope_info), ast_value_factory); |
| 366 outer_scope = new (zone) ModuleScope( | |
| 367 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); | |
| 368 } else { | 359 } else { |
| 369 DCHECK(context->IsCatchContext()); | 360 DCHECK_EQ(scope_info->scope_type(), CATCH_SCOPE); |
| 370 String* name = context->catch_name(); | 361 DCHECK_EQ(scope_info->LocalCount(), 1); |
| 362 String* name = scope_info->LocalName(0); |
| 371 outer_scope = new (zone) | 363 outer_scope = new (zone) |
| 372 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), | 364 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), |
| 373 Handle<ScopeInfo>(context->scope_info())); | 365 handle(scope_info)); |
| 374 } | 366 } |
| 375 if (deserialization_mode == DeserializationMode::kScopesOnly) { | 367 if (deserialization_mode == DeserializationMode::kScopesOnly) { |
| 376 outer_scope->scope_info_ = Handle<ScopeInfo>::null(); | 368 outer_scope->scope_info_ = Handle<ScopeInfo>::null(); |
| 377 } | 369 } |
| 378 if (current_scope != nullptr) { | 370 if (current_scope != nullptr) { |
| 379 outer_scope->AddInnerScope(current_scope); | 371 outer_scope->AddInnerScope(current_scope); |
| 380 DCHECK_IMPLIES( | |
| 381 deserialization_mode == DeserializationMode::kIncludingVariables, | |
| 382 current_scope->scope_info_->HasOuterScopeInfo()); | |
| 383 DCHECK_IMPLIES( | |
| 384 deserialization_mode == DeserializationMode::kIncludingVariables, | |
| 385 outer_scope->scope_info_->Equals( | |
| 386 current_scope->scope_info_->OuterScopeInfo())); | |
| 387 } | 372 } |
| 388 current_scope = outer_scope; | 373 current_scope = outer_scope; |
| 389 if (innermost_scope == nullptr) innermost_scope = current_scope; | 374 if (innermost_scope == nullptr) innermost_scope = current_scope; |
| 390 context = context->previous(); | 375 scope_info = scope_info->HasOuterScopeInfo() ? scope_info->OuterScopeInfo() |
| 376 : nullptr; |
| 391 } | 377 } |
| 392 | 378 |
| 393 if (innermost_scope == nullptr) return script_scope; | 379 if (innermost_scope == nullptr) return script_scope; |
| 394 script_scope->AddInnerScope(current_scope); | 380 script_scope->AddInnerScope(current_scope); |
| 395 #if DEBUG | |
| 396 if (deserialization_mode == DeserializationMode::kIncludingVariables) { | |
| 397 if (script_scope->scope_info_.is_null()) { | |
| 398 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); | |
| 399 } else { | |
| 400 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); | |
| 401 DCHECK(script_scope->scope_info_->Equals( | |
| 402 current_scope->scope_info_->OuterScopeInfo())); | |
| 403 } | |
| 404 } | |
| 405 #endif | |
| 406 return innermost_scope; | 381 return innermost_scope; |
| 407 } | 382 } |
| 408 | 383 |
| 409 DeclarationScope* Scope::AsDeclarationScope() { | 384 DeclarationScope* Scope::AsDeclarationScope() { |
| 410 DCHECK(is_declaration_scope()); | 385 DCHECK(is_declaration_scope()); |
| 411 return static_cast<DeclarationScope*>(this); | 386 return static_cast<DeclarationScope*>(this); |
| 412 } | 387 } |
| 413 | 388 |
| 414 const DeclarationScope* Scope::AsDeclarationScope() const { | 389 const DeclarationScope* Scope::AsDeclarationScope() const { |
| 415 DCHECK(is_declaration_scope()); | 390 DCHECK(is_declaration_scope()); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 factory->NewExpressionStatement(assignment, kNoSourcePosition); | 495 factory->NewExpressionStatement(assignment, kNoSourcePosition); |
| 521 delegate->set_statement(statement); | 496 delegate->set_statement(statement); |
| 522 } | 497 } |
| 523 } | 498 } |
| 524 } | 499 } |
| 525 | 500 |
| 526 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { | 501 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { |
| 527 DCHECK(info->literal() != NULL); | 502 DCHECK(info->literal() != NULL); |
| 528 DeclarationScope* scope = info->literal()->scope(); | 503 DeclarationScope* scope = info->literal()->scope(); |
| 529 | 504 |
| 530 if (!info->context().is_null() && !info->context()->IsNativeContext()) { | 505 Handle<ScopeInfo> outer_scope_info; |
| 506 if (info->maybe_outer_scope_info().ToHandle(&outer_scope_info)) { |
| 531 if (scope->outer_scope()) { | 507 if (scope->outer_scope()) { |
| 532 DeclarationScope* script_scope = new (info->zone()) | 508 DeclarationScope* script_scope = new (info->zone()) |
| 533 DeclarationScope(info->zone(), info->ast_value_factory()); | 509 DeclarationScope(info->zone(), info->ast_value_factory()); |
| 534 info->set_script_scope(script_scope); | 510 info->set_script_scope(script_scope); |
| 535 scope->ReplaceOuterScope(Scope::DeserializeScopeChain( | 511 scope->ReplaceOuterScope(Scope::DeserializeScopeChain( |
| 536 info->isolate(), info->zone(), *info->context(), script_scope, | 512 info->isolate(), info->zone(), *outer_scope_info, script_scope, |
| 537 info->ast_value_factory(), | 513 info->ast_value_factory(), |
| 538 Scope::DeserializationMode::kIncludingVariables)); | 514 Scope::DeserializationMode::kIncludingVariables)); |
| 539 } else { | 515 } else { |
| 540 DCHECK(info->context()->IsScriptContext()); | 516 DCHECK_EQ(outer_scope_info->scope_type(), SCRIPT_SCOPE); |
| 541 Handle<ScopeInfo> scope_info(info->context()->scope_info(), | 517 scope->SetScriptScopeInfo(outer_scope_info); |
| 542 info->isolate()); | |
| 543 scope->SetScriptScopeInfo(scope_info); | |
| 544 } | 518 } |
| 545 } | 519 } |
| 546 | 520 |
| 547 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) { | 521 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) { |
| 548 AstNodeFactory factory(info->ast_value_factory()); | 522 AstNodeFactory factory(info->ast_value_factory()); |
| 549 scope->HoistSloppyBlockFunctions(&factory); | 523 scope->HoistSloppyBlockFunctions(&factory); |
| 550 } | 524 } |
| 551 | 525 |
| 552 // We are compiling one of three cases: | 526 // We are compiling one of three cases: |
| 553 // 1) top-level code, | 527 // 1) top-level code, |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1837 Variable* function = | 1811 Variable* function = |
| 1838 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 1812 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
| 1839 bool is_function_var_in_context = | 1813 bool is_function_var_in_context = |
| 1840 function != nullptr && function->IsContextSlot(); | 1814 function != nullptr && function->IsContextSlot(); |
| 1841 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1815 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1842 (is_function_var_in_context ? 1 : 0); | 1816 (is_function_var_in_context ? 1 : 0); |
| 1843 } | 1817 } |
| 1844 | 1818 |
| 1845 } // namespace internal | 1819 } // namespace internal |
| 1846 } // namespace v8 | 1820 } // namespace v8 |
| OLD | NEW |