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 2820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3661 | 3648 |
3662 if (!parameters.is_simple) { | 3649 if (!parameters.is_simple) { |
3663 DCHECK_NOT_NULL(inner_scope); | 3650 DCHECK_NOT_NULL(inner_scope); |
3664 DCHECK_EQ(function_scope, scope()); | 3651 DCHECK_EQ(function_scope, scope()); |
3665 DCHECK_EQ(function_scope, inner_scope->outer_scope()); | 3652 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
3666 DCHECK_EQ(body, inner_block->statements()); | 3653 DCHECK_EQ(body, inner_block->statements()); |
3667 SetLanguageMode(function_scope, inner_scope->language_mode()); | 3654 SetLanguageMode(function_scope, inner_scope->language_mode()); |
3668 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); | 3655 Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); |
3669 | 3656 |
3670 if (is_sloppy(inner_scope->language_mode())) { | 3657 if (is_sloppy(inner_scope->language_mode())) { |
3671 InsertSloppyBlockFunctionVarBindings(inner_scope, CHECK_OK); | 3658 InsertSloppyBlockFunctionVarBindings(inner_scope); |
3672 } | 3659 } |
3673 | 3660 |
3674 // TODO(littledan): Merge the two rejection blocks into one | 3661 // TODO(littledan): Merge the two rejection blocks into one |
3675 if (IsAsyncFunction(kind)) { | 3662 if (IsAsyncFunction(kind)) { |
3676 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); | 3663 init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); |
3677 } | 3664 } |
3678 | 3665 |
3679 DCHECK_NOT_NULL(init_block); | 3666 DCHECK_NOT_NULL(init_block); |
3680 | 3667 |
3681 inner_scope->set_end_position(scanner()->location().end_pos); | 3668 inner_scope->set_end_position(scanner()->location().end_pos); |
3682 if (inner_scope->FinalizeBlockScope() != nullptr) { | 3669 if (inner_scope->FinalizeBlockScope() != nullptr) { |
3683 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); | 3670 CheckConflictingVarDeclarations(inner_scope, CHECK_OK); |
3684 InsertShadowingVarBindingInitializers(inner_block); | 3671 InsertShadowingVarBindingInitializers(inner_block); |
3685 } | 3672 } |
3686 inner_scope = nullptr; | 3673 inner_scope = nullptr; |
3687 | 3674 |
3688 result->Add(init_block, zone()); | 3675 result->Add(init_block, zone()); |
3689 result->Add(inner_block, zone()); | 3676 result->Add(inner_block, zone()); |
3690 } else { | 3677 } else { |
3691 DCHECK_EQ(inner_scope, function_scope); | 3678 DCHECK_EQ(inner_scope, function_scope); |
3692 if (is_sloppy(function_scope->language_mode())) { | 3679 if (is_sloppy(function_scope->language_mode())) { |
3693 InsertSloppyBlockFunctionVarBindings(function_scope, CHECK_OK); | 3680 InsertSloppyBlockFunctionVarBindings(function_scope); |
3694 } | 3681 } |
3695 } | 3682 } |
3696 | 3683 |
3697 if (function_type == FunctionLiteral::kNamedExpression) { | 3684 if (function_type == FunctionLiteral::kNamedExpression) { |
3698 // Now that we know the language mode, we can create the const assignment | 3685 // Now that we know the language mode, we can create the const assignment |
3699 // in the previously reserved spot. | 3686 // in the previously reserved spot. |
3700 DCHECK_EQ(function_scope, scope()); | 3687 DCHECK_EQ(function_scope, scope()); |
3701 Variable* fvar = function_scope->DeclareFunctionVar(function_name); | 3688 Variable* fvar = function_scope->DeclareFunctionVar(function_name); |
3702 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); | 3689 VariableProxy* fproxy = factory()->NewVariableProxy(fvar); |
3703 result->Set(kFunctionNameAssignmentIndex, | 3690 result->Set(kFunctionNameAssignmentIndex, |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3901 VariableProxy* to = NewUnresolved(name); | 3888 VariableProxy* to = NewUnresolved(name); |
3902 VariableProxy* from = factory()->NewVariableProxy(parameter); | 3889 VariableProxy* from = factory()->NewVariableProxy(parameter); |
3903 Expression* assignment = | 3890 Expression* assignment = |
3904 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); | 3891 factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition); |
3905 Statement* statement = | 3892 Statement* statement = |
3906 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 3893 factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
3907 inner_block->statements()->InsertAt(0, statement, zone()); | 3894 inner_block->statements()->InsertAt(0, statement, zone()); |
3908 } | 3895 } |
3909 } | 3896 } |
3910 | 3897 |
3911 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope, | 3898 void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) { |
3912 bool* ok) { | 3899 // For the outermost eval scope, we cannot hoist during parsing: let |
3913 scope->HoistSloppyBlockFunctions(factory(), CHECK_OK_VOID); | 3900 // declarations in the surrounding scope may prevent hoisting, but the |
3914 | 3901 // information is unaccessible during parsing. In this case, we hoist later in |
3915 SloppyBlockFunctionMap* map = scope->sloppy_block_function_map(); | 3902 // DeclarationScope::Analyze. |
3916 for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) { | 3903 if (scope->is_eval_scope() && scope->outer_scope() == original_scope_) { |
3917 // Write in assignments to var for each block-scoped function declaration | 3904 return; |
3918 auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value); | |
3919 for (SloppyBlockFunctionStatement* delegate = delegates; | |
3920 delegate != nullptr; delegate = delegate->next()) { | |
3921 if (delegate->to() == nullptr) { | |
3922 continue; | |
3923 } | |
3924 Expression* assignment = factory()->NewAssignment( | |
3925 Token::ASSIGN, delegate->to(), delegate->from(), kNoSourcePosition); | |
3926 Statement* statement = | |
3927 factory()->NewExpressionStatement(assignment, kNoSourcePosition); | |
3928 delegate->set_statement(statement); | |
3929 } | |
3930 } | 3905 } |
| 3906 scope->HoistSloppyBlockFunctions(factory()); |
3931 } | 3907 } |
3932 | 3908 |
3933 | |
3934 // ---------------------------------------------------------------------------- | 3909 // ---------------------------------------------------------------------------- |
3935 // Parser support | 3910 // Parser support |
3936 | 3911 |
3937 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | 3912 bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
3938 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) { | 3913 for (ParserTarget* t = target_stack_; t != NULL; t = t->previous()) { |
3939 if (ContainsLabel(t->statement()->labels(), label)) return true; | 3914 if (ContainsLabel(t->statement()->labels(), label)) return true; |
3940 } | 3915 } |
3941 return false; | 3916 return false; |
3942 } | 3917 } |
3943 | 3918 |
(...skipping 1683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5627 node->Print(Isolate::Current()); | 5602 node->Print(Isolate::Current()); |
5628 } | 5603 } |
5629 #endif // DEBUG | 5604 #endif // DEBUG |
5630 | 5605 |
5631 #undef CHECK_OK | 5606 #undef CHECK_OK |
5632 #undef CHECK_OK_VOID | 5607 #undef CHECK_OK_VOID |
5633 #undef CHECK_FAILED | 5608 #undef CHECK_FAILED |
5634 | 5609 |
5635 } // namespace internal | 5610 } // namespace internal |
5636 } // namespace v8 | 5611 } // namespace v8 |
OLD | NEW |