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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 // function scope in which we are evaluating. | 326 // function scope in which we are evaluating. |
327 if (context->IsDebugEvaluateContext()) { | 327 if (context->IsDebugEvaluateContext()) { |
328 outer_scope->set_is_debug_evaluate_scope(); | 328 outer_scope->set_is_debug_evaluate_scope(); |
329 } | 329 } |
330 } else if (context->IsScriptContext()) { | 330 } else if (context->IsScriptContext()) { |
331 // If we reach a script context, it's the outermost context with scope | 331 // If we reach a script context, it's the outermost context with scope |
332 // info. The next context will be the native context. Install the scope | 332 // info. The next context will be the native context. Install the scope |
333 // info of this script context onto the existing script scope to avoid | 333 // info of this script context onto the existing script scope to avoid |
334 // nesting script scopes. | 334 // nesting script scopes. |
335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
336 script_scope->SetScriptScopeInfo(scope_info); | 336 if (deserialization_mode == DeserializationMode::kIncludingVariables) { |
| 337 script_scope->SetScriptScopeInfo(scope_info); |
| 338 } |
337 DCHECK(context->previous()->IsNativeContext()); | 339 DCHECK(context->previous()->IsNativeContext()); |
338 break; | 340 break; |
339 } else if (context->IsFunctionContext()) { | 341 } else if (context->IsFunctionContext()) { |
340 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 342 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
341 // TODO(neis): For an eval scope, we currently create an ordinary function | 343 // TODO(neis): For an eval scope, we currently create an ordinary function |
342 // context. This is wrong and needs to be fixed. | 344 // context. This is wrong and needs to be fixed. |
343 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 345 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
344 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 346 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
345 scope_info->scope_type() == EVAL_SCOPE); | 347 scope_info->scope_type() == EVAL_SCOPE); |
346 outer_scope = | 348 outer_scope = |
(...skipping 16 matching lines...) Expand all Loading... |
363 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); | 365 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); |
364 outer_scope = new (zone) ModuleScope( | 366 outer_scope = new (zone) ModuleScope( |
365 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); | 367 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); |
366 } else { | 368 } else { |
367 DCHECK(context->IsCatchContext()); | 369 DCHECK(context->IsCatchContext()); |
368 String* name = context->catch_name(); | 370 String* name = context->catch_name(); |
369 outer_scope = new (zone) | 371 outer_scope = new (zone) |
370 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), | 372 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), |
371 Handle<ScopeInfo>(context->scope_info())); | 373 Handle<ScopeInfo>(context->scope_info())); |
372 } | 374 } |
| 375 if (deserialization_mode == DeserializationMode::kScopesOnly) { |
| 376 outer_scope->scope_info_ = Handle<ScopeInfo>::null(); |
| 377 } |
373 if (current_scope != nullptr) { | 378 if (current_scope != nullptr) { |
374 outer_scope->AddInnerScope(current_scope); | 379 outer_scope->AddInnerScope(current_scope); |
375 DCHECK_IMPLIES( | 380 DCHECK_IMPLIES( |
376 deserialization_mode == DeserializationMode::kKeepScopeInfo, | 381 deserialization_mode == DeserializationMode::kIncludingVariables, |
377 current_scope->scope_info_->HasOuterScopeInfo()); | 382 current_scope->scope_info_->HasOuterScopeInfo()); |
378 DCHECK_IMPLIES( | 383 DCHECK_IMPLIES( |
379 deserialization_mode == DeserializationMode::kKeepScopeInfo, | 384 deserialization_mode == DeserializationMode::kIncludingVariables, |
380 outer_scope->scope_info_->Equals( | 385 outer_scope->scope_info_->Equals( |
381 current_scope->scope_info_->OuterScopeInfo())); | 386 current_scope->scope_info_->OuterScopeInfo())); |
382 } | 387 } |
383 current_scope = outer_scope; | 388 current_scope = outer_scope; |
384 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | |
385 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | |
386 } | |
387 if (innermost_scope == nullptr) innermost_scope = current_scope; | 389 if (innermost_scope == nullptr) innermost_scope = current_scope; |
388 context = context->previous(); | 390 context = context->previous(); |
389 } | 391 } |
390 | 392 |
391 if (innermost_scope == nullptr) return script_scope; | 393 if (innermost_scope == nullptr) return script_scope; |
392 script_scope->AddInnerScope(current_scope); | 394 script_scope->AddInnerScope(current_scope); |
393 #if DEBUG | 395 #if DEBUG |
394 if (deserialization_mode == DeserializationMode::kKeepScopeInfo) { | 396 if (deserialization_mode == DeserializationMode::kIncludingVariables) { |
395 if (script_scope->scope_info_.is_null()) { | 397 if (script_scope->scope_info_.is_null()) { |
396 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); | 398 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); |
397 } else { | 399 } else { |
398 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); | 400 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); |
399 DCHECK(script_scope->scope_info_->Equals( | 401 DCHECK(script_scope->scope_info_->Equals( |
400 current_scope->scope_info_->OuterScopeInfo())); | 402 current_scope->scope_info_->OuterScopeInfo())); |
401 } | 403 } |
402 } | 404 } |
403 #endif | 405 #endif |
404 return innermost_scope; | 406 return innermost_scope; |
405 } | 407 } |
406 | 408 |
407 void Scope::DeserializeScopeInfo(Isolate* isolate, | |
408 AstValueFactory* ast_value_factory) { | |
409 if (scope_info_.is_null()) return; | |
410 | |
411 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); | |
412 | |
413 // Internalize context local variables. | |
414 for (int var = 0; var < scope_info_->ContextLocalCount(); ++var) { | |
415 Handle<String> name_handle(scope_info_->ContextLocalName(var), isolate); | |
416 const AstRawString* name = ast_value_factory->GetString(name_handle); | |
417 int index = Context::MIN_CONTEXT_SLOTS + var; | |
418 VariableMode mode = scope_info_->ContextLocalMode(var); | |
419 InitializationFlag init_flag = scope_info_->ContextLocalInitFlag(var); | |
420 MaybeAssignedFlag maybe_assigned_flag = | |
421 scope_info_->ContextLocalMaybeAssignedFlag(var); | |
422 VariableLocation location = VariableLocation::CONTEXT; | |
423 VariableKind kind = NORMAL_VARIABLE; | |
424 if (index == scope_info_->ReceiverContextSlotIndex()) { | |
425 kind = THIS_VARIABLE; | |
426 } | |
427 | |
428 Variable* result = variables_.Declare(zone(), this, name, mode, kind, | |
429 init_flag, maybe_assigned_flag); | |
430 result->AllocateTo(location, index); | |
431 } | |
432 | |
433 // Internalize function proxy for this scope. | |
434 if (scope_info_->HasFunctionName()) { | |
435 Handle<String> name_handle(scope_info_->FunctionName(), isolate); | |
436 const AstRawString* name = ast_value_factory->GetString(name_handle); | |
437 int index = scope_info_->FunctionContextSlotIndex(*name_handle); | |
438 if (index >= 0) { | |
439 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); | |
440 result->AllocateTo(VariableLocation::CONTEXT, index); | |
441 } | |
442 } | |
443 | |
444 scope_info_ = Handle<ScopeInfo>::null(); | |
445 } | |
446 | |
447 DeclarationScope* Scope::AsDeclarationScope() { | 409 DeclarationScope* Scope::AsDeclarationScope() { |
448 DCHECK(is_declaration_scope()); | 410 DCHECK(is_declaration_scope()); |
449 return static_cast<DeclarationScope*>(this); | 411 return static_cast<DeclarationScope*>(this); |
450 } | 412 } |
451 | 413 |
452 const DeclarationScope* Scope::AsDeclarationScope() const { | 414 const DeclarationScope* Scope::AsDeclarationScope() const { |
453 DCHECK(is_declaration_scope()); | 415 DCHECK(is_declaration_scope()); |
454 return static_cast<const DeclarationScope*>(this); | 416 return static_cast<const DeclarationScope*>(this); |
455 } | 417 } |
456 | 418 |
457 ModuleScope* Scope::AsModuleScope() { | 419 ModuleScope* Scope::AsModuleScope() { |
458 DCHECK(is_module_scope()); | 420 DCHECK(is_module_scope()); |
459 return static_cast<ModuleScope*>(this); | 421 return static_cast<ModuleScope*>(this); |
460 } | 422 } |
461 | 423 |
462 const ModuleScope* Scope::AsModuleScope() const { | 424 const ModuleScope* Scope::AsModuleScope() const { |
463 DCHECK(is_module_scope()); | 425 DCHECK(is_module_scope()); |
464 return static_cast<const ModuleScope*>(this); | 426 return static_cast<const ModuleScope*>(this); |
465 } | 427 } |
466 | 428 |
467 int Scope::num_parameters() const { | 429 int Scope::num_parameters() const { |
468 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; | 430 return is_declaration_scope() ? AsDeclarationScope()->num_parameters() : 0; |
469 } | 431 } |
470 | 432 |
471 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory, | 433 void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) { |
472 bool* ok) { | |
473 DCHECK(is_sloppy(language_mode())); | 434 DCHECK(is_sloppy(language_mode())); |
474 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() || | 435 DCHECK(is_function_scope() || is_eval_scope() || is_script_scope() || |
475 (is_block_scope() && outer_scope()->is_function_scope())); | 436 (is_block_scope() && outer_scope()->is_function_scope())); |
476 DCHECK(HasSimpleParameters() || is_block_scope()); | 437 DCHECK(HasSimpleParameters() || is_block_scope()); |
477 bool has_simple_parameters = HasSimpleParameters(); | 438 bool has_simple_parameters = HasSimpleParameters(); |
478 // For each variable which is used as a function declaration in a sloppy | 439 // For each variable which is used as a function declaration in a sloppy |
479 // block, | 440 // block, |
480 SloppyBlockFunctionMap* map = sloppy_block_function_map(); | 441 SloppyBlockFunctionMap* map = sloppy_block_function_map(); |
481 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 442 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { |
482 AstRawString* name = static_cast<AstRawString*>(p->key); | 443 AstRawString* name = static_cast<AstRawString*>(p->key); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 | 499 |
539 // Declare a var-style binding for the function in the outer scope | 500 // Declare a var-style binding for the function in the outer scope |
540 if (!var_created) { | 501 if (!var_created) { |
541 var_created = true; | 502 var_created = true; |
542 VariableProxy* proxy = NewUnresolved(factory, name); | 503 VariableProxy* proxy = NewUnresolved(factory, name); |
543 Declaration* declaration = | 504 Declaration* declaration = |
544 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition); | 505 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition); |
545 // Based on the preceding check, it doesn't matter what we pass as | 506 // Based on the preceding check, it doesn't matter what we pass as |
546 // allow_harmony_restrictive_generators and | 507 // allow_harmony_restrictive_generators and |
547 // sloppy_mode_block_scope_function_redefinition. | 508 // sloppy_mode_block_scope_function_redefinition. |
| 509 bool ok = true; |
548 DeclareVariable(declaration, VAR, | 510 DeclareVariable(declaration, VAR, |
549 Variable::DefaultInitializationFlag(VAR), false, | 511 Variable::DefaultInitializationFlag(VAR), false, |
550 nullptr, ok); | 512 nullptr, &ok); |
551 DCHECK(*ok); // Based on the preceding check, this should not fail | 513 CHECK(ok); // Based on the preceding check, this should not fail |
552 if (!*ok) return; | |
553 } | 514 } |
554 | 515 |
555 // Create VariableProxies for creating an assignment statement | 516 Expression* assignment = factory->NewAssignment( |
556 // (later). Read from the local lexical scope and write to the function | 517 Token::ASSIGN, NewUnresolved(factory, name), |
557 // scope. | 518 delegate->scope()->NewUnresolved(factory, name), kNoSourcePosition); |
558 delegate->set_to(NewUnresolved(factory, name)); | 519 Statement* statement = |
559 delegate->set_from(delegate->scope()->NewUnresolved(factory, name)); | 520 factory->NewExpressionStatement(assignment, kNoSourcePosition); |
| 521 delegate->set_statement(statement); |
560 } | 522 } |
561 } | 523 } |
562 } | 524 } |
563 | 525 |
564 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { | 526 void DeclarationScope::Analyze(ParseInfo* info, AnalyzeMode mode) { |
565 DCHECK(info->literal() != NULL); | 527 DCHECK(info->literal() != NULL); |
566 DeclarationScope* scope = info->literal()->scope(); | 528 DeclarationScope* scope = info->literal()->scope(); |
567 | 529 |
| 530 if (!info->context().is_null() && !info->context()->IsNativeContext()) { |
| 531 if (scope->outer_scope()) { |
| 532 DeclarationScope* script_scope = new (info->zone()) |
| 533 DeclarationScope(info->zone(), info->ast_value_factory()); |
| 534 info->set_script_scope(script_scope); |
| 535 scope->ReplaceOuterScope(Scope::DeserializeScopeChain( |
| 536 info->isolate(), info->zone(), *info->context(), script_scope, |
| 537 info->ast_value_factory(), |
| 538 Scope::DeserializationMode::kIncludingVariables)); |
| 539 } else { |
| 540 DCHECK(info->context()->IsScriptContext()); |
| 541 Handle<ScopeInfo> scope_info(info->context()->scope_info(), |
| 542 info->isolate()); |
| 543 scope->SetScriptScopeInfo(scope_info); |
| 544 } |
| 545 } |
| 546 |
| 547 if (scope->is_eval_scope() && is_sloppy(scope->language_mode())) { |
| 548 AstNodeFactory factory(info->ast_value_factory()); |
| 549 scope->HoistSloppyBlockFunctions(&factory); |
| 550 } |
| 551 |
568 // We are compiling one of three cases: | 552 // We are compiling one of three cases: |
569 // 1) top-level code, | 553 // 1) top-level code, |
570 // 2) a function/eval/module on the top-level | 554 // 2) a function/eval/module on the top-level |
571 // 3) a function/eval in a scope that was already resolved. | 555 // 3) a function/eval in a scope that was already resolved. |
572 DCHECK(scope->scope_type() == SCRIPT_SCOPE || | 556 DCHECK(scope->scope_type() == SCRIPT_SCOPE || |
573 scope->outer_scope()->scope_type() == SCRIPT_SCOPE || | 557 scope->outer_scope()->scope_type() == SCRIPT_SCOPE || |
574 scope->outer_scope()->already_resolved_); | 558 scope->outer_scope()->already_resolved_); |
575 | 559 |
576 scope->AllocateVariables(info, mode); | 560 scope->AllocateVariables(info, mode); |
577 | 561 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 } | 724 } |
741 } | 725 } |
742 outer_closure->locals_.Rewind(top_local_); | 726 outer_closure->locals_.Rewind(top_local_); |
743 outer_closure->decls_.Rewind(top_decl_); | 727 outer_closure->decls_.Rewind(top_decl_); |
744 } | 728 } |
745 | 729 |
746 void Scope::ReplaceOuterScope(Scope* outer) { | 730 void Scope::ReplaceOuterScope(Scope* outer) { |
747 DCHECK_NOT_NULL(outer); | 731 DCHECK_NOT_NULL(outer); |
748 DCHECK_NOT_NULL(outer_scope_); | 732 DCHECK_NOT_NULL(outer_scope_); |
749 DCHECK(!already_resolved_); | 733 DCHECK(!already_resolved_); |
750 DCHECK(!outer->already_resolved_); | |
751 DCHECK(!outer_scope_->already_resolved_); | |
752 outer_scope_->RemoveInnerScope(this); | 734 outer_scope_->RemoveInnerScope(this); |
753 outer->AddInnerScope(this); | 735 outer->AddInnerScope(this); |
754 outer_scope_ = outer; | 736 outer_scope_ = outer; |
755 } | 737 } |
756 | 738 |
757 | 739 |
758 void Scope::PropagateUsageFlagsToScope(Scope* other) { | 740 void Scope::PropagateUsageFlagsToScope(Scope* other) { |
759 DCHECK_NOT_NULL(other); | 741 DCHECK_NOT_NULL(other); |
760 DCHECK(!already_resolved_); | 742 DCHECK(!already_resolved_); |
761 DCHECK(!other->already_resolved_); | 743 DCHECK(!other->already_resolved_); |
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 Variable* function = | 1837 Variable* function = |
1856 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 1838 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
1857 bool is_function_var_in_context = | 1839 bool is_function_var_in_context = |
1858 function != nullptr && function->IsContextSlot(); | 1840 function != nullptr && function->IsContextSlot(); |
1859 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1841 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1860 (is_function_var_in_context ? 1 : 0); | 1842 (is_function_var_in_context ? 1 : 0); |
1861 } | 1843 } |
1862 | 1844 |
1863 } // namespace internal | 1845 } // namespace internal |
1864 } // namespace v8 | 1846 } // namespace v8 |
OLD | NEW |