| 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 |