Chromium Code Reviews| 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/parsing/parser.h" | 5 #include "src/parsing/parser.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/ast/ast-expression-rewriter.h" | 10 #include "src/ast/ast-expression-rewriter.h" |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 } | 596 } |
| 597 if (info->ast_value_factory() == NULL) { | 597 if (info->ast_value_factory() == NULL) { |
| 598 // info takes ownership of AstValueFactory. | 598 // info takes ownership of AstValueFactory. |
| 599 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); | 599 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); |
| 600 info->set_ast_value_factory_owned(); | 600 info->set_ast_value_factory_owned(); |
| 601 ast_value_factory_ = info->ast_value_factory(); | 601 ast_value_factory_ = info->ast_value_factory(); |
| 602 ast_node_factory_.set_ast_value_factory(ast_value_factory_); | 602 ast_node_factory_.set_ast_value_factory(ast_value_factory_); |
| 603 } | 603 } |
| 604 } | 604 } |
| 605 | 605 |
| 606 void Parser::DeserializeScopeChain( | 606 void Parser::DeserializeScopeChain(ParseInfo* info, |
| 607 ParseInfo* info, Handle<Context> context, | 607 MaybeHandle<Context> maybe_context) { |
| 608 Scope::DeserializationMode deserialization_mode) { | |
| 609 DCHECK(ThreadId::Current().Equals(info->isolate()->thread_id())); | 608 DCHECK(ThreadId::Current().Equals(info->isolate()->thread_id())); |
| 610 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native | 609 // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native |
| 611 // context, which will have the "this" binding for script scopes. | 610 // context, which will have the "this" binding for script scopes. |
| 612 DeclarationScope* script_scope = NewScriptScope(); | 611 DeclarationScope* script_scope = NewScriptScope(); |
| 613 info->set_script_scope(script_scope); | 612 info->set_script_scope(script_scope); |
| 614 Scope* scope = script_scope; | 613 Scope* scope = script_scope; |
| 615 if (!context.is_null() && !context->IsNativeContext()) { | 614 Handle<Context> context; |
| 616 scope = Scope::DeserializeScopeChain(info->isolate(), zone(), *context, | 615 if (maybe_context.ToHandle(&context) && !context->IsNativeContext()) { |
| 617 script_scope, ast_value_factory(), | 616 scope = Scope::DeserializeScopeChain( |
| 618 deserialization_mode); | 617 info->isolate(), zone(), *context, script_scope, ast_value_factory(), |
| 618 Scope::DeserializationMode::kScopesOnly); | |
| 619 DCHECK(!info->is_module() || scope->is_module_scope()); | 619 DCHECK(!info->is_module() || scope->is_module_scope()); |
| 620 if (info->context().is_null()) { | |
| 621 DCHECK(deserialization_mode == | |
| 622 Scope::DeserializationMode::kDeserializeOffHeap); | |
| 623 } else { | |
| 624 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this | |
| 625 // means the Parser cannot operate independent of the V8 heap. Tell the | |
| 626 // string table to internalize strings and values right after they're | |
| 627 // created. This kind of parsing can only be done in the main thread. | |
| 628 DCHECK(parsing_on_main_thread_); | |
| 629 ast_value_factory()->Internalize(info->isolate()); | |
| 630 } | |
| 631 } | 620 } |
| 632 original_scope_ = scope; | 621 original_scope_ = scope; |
| 633 } | 622 } |
| 634 | 623 |
| 635 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { | 624 FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) { |
| 636 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, | 625 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, |
| 637 // see comment for HistogramTimerScope class. | 626 // see comment for HistogramTimerScope class. |
| 638 | 627 |
| 639 // It's OK to use the Isolate & counters here, since this function is only | 628 // It's OK to use the Isolate & counters here, since this function is only |
| 640 // called in the main thread. | 629 // called in the main thread. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 653 | 642 |
| 654 // Initialize parser state. | 643 // Initialize parser state. |
| 655 CompleteParserRecorder recorder; | 644 CompleteParserRecorder recorder; |
| 656 | 645 |
| 657 if (produce_cached_parse_data()) { | 646 if (produce_cached_parse_data()) { |
| 658 log_ = &recorder; | 647 log_ = &recorder; |
| 659 } else if (consume_cached_parse_data()) { | 648 } else if (consume_cached_parse_data()) { |
| 660 cached_parse_data_->Initialize(); | 649 cached_parse_data_->Initialize(); |
| 661 } | 650 } |
| 662 | 651 |
| 663 DeserializeScopeChain(info, info->context(), | 652 DeserializeScopeChain(info, info->context()); |
| 664 Scope::DeserializationMode::kKeepScopeInfo); | |
| 665 | 653 |
| 666 source = String::Flatten(source); | 654 source = String::Flatten(source); |
| 667 FunctionLiteral* result; | 655 FunctionLiteral* result; |
| 668 | 656 |
| 669 { | 657 { |
| 670 std::unique_ptr<Utf16CharacterStream> stream; | 658 std::unique_ptr<Utf16CharacterStream> stream; |
| 671 if (source->IsExternalTwoByteString()) { | 659 if (source->IsExternalTwoByteString()) { |
| 672 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( | 660 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( |
| 673 Handle<ExternalTwoByteString>::cast(source), 0, source->length())); | 661 Handle<ExternalTwoByteString>::cast(source), 0, source->length())); |
| 674 } else if (source->IsExternalOneByteString()) { | 662 } else if (source->IsExternalOneByteString()) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 773 if (ok && is_strict(language_mode())) { | 761 if (ok && is_strict(language_mode())) { |
| 774 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); | 762 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); |
| 775 CheckDecimalLiteralWithLeadingZero(beg_pos, | 763 CheckDecimalLiteralWithLeadingZero(beg_pos, |
| 776 scanner()->location().end_pos); | 764 scanner()->location().end_pos); |
| 777 } | 765 } |
| 778 if (ok && is_sloppy(language_mode())) { | 766 if (ok && is_sloppy(language_mode())) { |
| 779 // TODO(littledan): Function bindings on the global object that modify | 767 // TODO(littledan): Function bindings on the global object that modify |
| 780 // pre-existing bindings should be made writable, enumerable and | 768 // pre-existing bindings should be made writable, enumerable and |
| 781 // nonconfigurable if possible, whereas this code will leave attributes | 769 // nonconfigurable if possible, whereas this code will leave attributes |
| 782 // unchanged if the property already exists. | 770 // unchanged if the property already exists. |
| 783 InsertSloppyBlockFunctionVarBindings(scope, &ok); | 771 InsertSloppyBlockFunctionVarBindings(scope); |
| 784 } | 772 } |
| 785 if (ok) { | 773 if (ok) { |
| 786 CheckConflictingVarDeclarations(scope, &ok); | 774 CheckConflictingVarDeclarations(scope, &ok); |
| 787 } | 775 } |
| 788 | 776 |
| 789 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { | 777 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { |
| 790 if (body->length() != 1 || | 778 if (body->length() != 1 || |
| 791 !body->at(0)->IsExpressionStatement() || | 779 !body->at(0)->IsExpressionStatement() || |
| 792 !body->at(0)->AsExpressionStatement()-> | 780 !body->at(0)->AsExpressionStatement()-> |
| 793 expression()->IsFunctionLiteral()) { | 781 expression()->IsFunctionLiteral()) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 819 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy); | 807 RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy); |
| 820 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); | 808 HistogramTimerScope timer_scope(isolate->counters()->parse_lazy()); |
| 821 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy"); | 809 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.ParseLazy"); |
| 822 Handle<String> source(String::cast(info->script()->source())); | 810 Handle<String> source(String::cast(info->script()->source())); |
| 823 isolate->counters()->total_parse_size()->Increment(source->length()); | 811 isolate->counters()->total_parse_size()->Increment(source->length()); |
| 824 base::ElapsedTimer timer; | 812 base::ElapsedTimer timer; |
| 825 if (FLAG_trace_parse) { | 813 if (FLAG_trace_parse) { |
| 826 timer.Start(); | 814 timer.Start(); |
| 827 } | 815 } |
| 828 Handle<SharedFunctionInfo> shared_info = info->shared_info(); | 816 Handle<SharedFunctionInfo> shared_info = info->shared_info(); |
| 829 DeserializeScopeChain(info, info->context(), | 817 DeserializeScopeChain(info, info->context()); |
| 830 Scope::DeserializationMode::kKeepScopeInfo); | |
| 831 | 818 |
| 832 // Initialize parser state. | 819 // Initialize parser state. |
| 833 source = String::Flatten(source); | 820 source = String::Flatten(source); |
| 834 FunctionLiteral* result; | 821 FunctionLiteral* result; |
| 835 { | 822 { |
| 836 std::unique_ptr<Utf16CharacterStream> stream; | 823 std::unique_ptr<Utf16CharacterStream> stream; |
| 837 if (source->IsExternalTwoByteString()) { | 824 if (source->IsExternalTwoByteString()) { |
| 838 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( | 825 stream.reset(new ExternalTwoByteStringUtf16CharacterStream( |
| 839 Handle<ExternalTwoByteString>::cast(source), | 826 Handle<ExternalTwoByteString>::cast(source), |
| 840 shared_info->start_position(), shared_info->end_position())); | 827 shared_info->start_position(), shared_info->end_position())); |
| (...skipping 2818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3659 | 3646 |
| 3660 if (!parameters.is_simple) { | 3647 if (!parameters.is_simple) { |
| 3661 DCHECK_NOT_NULL(inner_scope); | 3648 DCHECK_NOT_NULL(inner_scope); |
| 3662 DCHECK_EQ(function_scope, scope()); | 3649 DCHECK_EQ(function_scope, scope()); |
| 3663 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | 3650 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
| 3664 DCHECK_EQ(body, inner_block->statements()); | 3651 DCHECK_EQ(body, inner_block->statements()); |
| 3665 SetLanguageMode(function_scope, inner_scope->language_mode()); | 3652 SetLanguageMode(function_scope, inner_scope->language_mode()); |
| 3666 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 3653 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
| 3667 | 3654 |
| 3668 if (is_sloppy(inner_scope->language_mode())) { | 3655 if (is_sloppy(inner_scope->language_mode())) { |
| 3669 InsertSloppyBlockFunctionVarBindings(inner_scope, CHECK_OK); | 3656 InsertSloppyBlockFunctionVarBindings(inner_scope); |
| 3670 } | 3657 } |
| 3671 | 3658 |
| 3672 // TODO(littledan): Merge the two rejection blocks into one | 3659 // TODO(littledan): Merge the two rejection blocks into one |
| 3673 if (IsAsyncFunction(kind)) { | 3660 if (IsAsyncFunction(kind)) { |
| 3674 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); | 3661 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
| 3675 } | 3662 } |
| 3676 | 3663 |
| 3677 DCHECK_NOT_NULL(init_block); | 3664 DCHECK_NOT_NULL(init_block); |
| 3678 | 3665 |
| 3679 inner_scope->set_end_position(scanner()->location().end_pos); | 3666 inner_scope->set_end_position(scanner()->location().end_pos); |
| 3680 if (inner_scope->FinalizeBlockScope() != nullptr) { | 3667 if (inner_scope->FinalizeBlockScope() != nullptr) { |
| 3681 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 3668 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
| 3682 InsertShadowingVarBindingInitializers(inner_block); | 3669 InsertShadowingVarBindingInitializers(inner_block); |
| 3683 } | 3670 } |
| 3684 inner_scope = nullptr; | 3671 inner_scope = nullptr; |
| 3685 | 3672 |
| 3686 result->Add(init_block, zone()); | 3673 result->Add(init_block, zone()); |
| 3687 result->Add(inner_block, zone()); | 3674 result->Add(inner_block, zone()); |
| 3688 } else { | 3675 } else { |
| 3689 DCHECK_EQ(inner_scope, function_scope); | 3676 DCHECK_EQ(inner_scope, function_scope); |
| 3690 if (is_sloppy(function_scope->language_mode())) { | 3677 if (is_sloppy(function_scope->language_mode())) { |
| 3691 InsertSloppyBlockFunctionVarBindings(function_scope, CHECK_OK); | 3678 InsertSloppyBlockFunctionVarBindings(function_scope); |
| 3692 } | 3679 } |
| 3693 } | 3680 } |
| 3694 | 3681 |
| 3695 if (function_type == FunctionLiteral::kNamedExpression) { | 3682 if (function_type == FunctionLiteral::kNamedExpression) { |
| 3696 // Now that we know the language mode, we can create the const assignment | 3683 // Now that we know the language mode, we can create the const assignment |
| 3697 // in the previously reserved spot. | 3684 // in the previously reserved spot. |
| 3698 DCHECK_EQ(function_scope, scope()); | 3685 DCHECK_EQ(function_scope, scope()); |
| 3699 Variable* fvar = function_scope->DeclareFunctionVar(function_name); | 3686 Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
| 3700 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | 3687 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
| 3701 result->Set(kFunctionNameAssignmentIndex, | 3688 result->Set(kFunctionNameAssignmentIndex, |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3899 VariableProxy* to = NewUnresolved(name); | 3886 VariableProxy* to = NewUnresolved(name); |
| 3900 VariableProxy* from = factory()->NewVariableProxy(parameter); | 3887 VariableProxy* from = factory()->NewVariableProxy(parameter); |
| 3901 Expression* assignment = | 3888 Expression* assignment = |
| 3902 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); | 3889 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); |
| 3903 Statement* statement = | 3890 Statement* statement = |
| 3904 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 3891 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
| 3905 inner_block->statements()->InsertAt(0, statement, zone()); | 3892 inner_block->statements()->InsertAt(0, statement, zone()); |
| 3906 } | 3893 } |
| 3907 } | 3894 } |
| 3908 | 3895 |
| 3909 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope, | 3896 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) { |
| 3910 bool* ok) { | 3897 // For the outer most eval scope (which is inside a script scope), don't |
| 3911 scope->HoistSloppyBlockFunctions(factory(), CHECK_OK_VOID); | 3898 // hoist during parsing, but later during DeclarationScope::Analyze when the |
| 3912 | 3899 // actual scope chain is available. |
|
marja
2016/09/14 09:45:21
Nit: this comment still doesn't explain why. Also,
jochen (gone - plz use gerrit)
2016/09/14 11:27:30
done
| |
| 3913 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 3900 if (scope->is_eval_scope() && scope->outer_scope() == original_scope_) { |
| 3914 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 3901 return; |
| 3915 // Write in assignments to var for each block-scoped function declaration | |
| 3916 auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value); | |
| 3917 for (SloppyBlockFunctionStatement* delegate = delegates; | |
| 3918 delegate != nullptr; delegate = delegate->next()) { | |
| 3919 if (delegate->to() == nullptr) { | |
| 3920 continue; | |
| 3921 } | |
| 3922 Expression* assignment = factory()->NewAssignment( | |
| 3923 Token::ASSIGN, delegate->to(), delegate->from(), kNoSourcePosition); | |
| 3924 Statement* statement = | |
| 3925 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | |
| 3926 delegate->set_statement(statement); | |
| 3927 } | |
| 3928 } | 3902 } |
| 3903 scope->HoistSloppyBlockFunctions(factory()); | |
| 3929 } | 3904 } |
| 3930 | 3905 |
| 3931 | |
| 3932 // ---------------------------------------------------------------------------- | 3906 // ---------------------------------------------------------------------------- |
| 3933 // Parser support | 3907 // Parser support |
| 3934 | 3908 |
| 3935 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | 3909 bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
| 3936 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) { | 3910 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) { |
| 3937 if (ContainsLabel(t->statement()->labels(), label)) return true; | 3911 if (ContainsLabel(t->statement()->labels(), label)) return true; |
| 3938 } | 3912 } |
| 3939 return false; | 3913 return false; |
| 3940 } | 3914 } |
| 3941 | 3915 |
| (...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5620 node->Print(Isolate::Current()); | 5594 node->Print(Isolate::Current()); |
| 5621 } | 5595 } |
| 5622 #endif // DEBUG | 5596 #endif // DEBUG |
| 5623 | 5597 |
| 5624 #undef CHECK_OK | 5598 #undef CHECK_OK |
| 5625 #undef CHECK_OK_VOID | 5599 #undef CHECK_OK_VOID |
| 5626 #undef CHECK_FAILED | 5600 #undef CHECK_FAILED |
| 5627 | 5601 |
| 5628 } // namespace internal | 5602 } // namespace internal |
| 5629 } // namespace v8 | 5603 } // namespace v8 |
| OLD | NEW |