Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/parser.cc

Issue 566553002: Add script streaming API. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/scanner-character-streams.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/base/platform/platform.h" 9 #include "src/base/platform/platform.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 original_scope_(NULL), 743 original_scope_(NULL),
744 target_stack_(NULL), 744 target_stack_(NULL),
745 cached_parse_data_(NULL), 745 cached_parse_data_(NULL),
746 info_(info), 746 info_(info),
747 has_pending_error_(false), 747 has_pending_error_(false),
748 pending_error_message_(NULL), 748 pending_error_message_(NULL),
749 pending_error_arg_(NULL), 749 pending_error_arg_(NULL),
750 pending_error_char_arg_(NULL), 750 pending_error_char_arg_(NULL),
751 total_preparse_skipped_(0), 751 total_preparse_skipped_(0),
752 pre_parse_timer_(NULL) { 752 pre_parse_timer_(NULL) {
753 DCHECK(!script().is_null()); 753 DCHECK(!script().is_null() || info->source_stream() != NULL);
754 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); 754 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
755 set_allow_modules(!info->is_native() && FLAG_harmony_modules); 755 set_allow_modules(!info->is_native() && FLAG_harmony_modules);
756 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); 756 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
757 set_allow_lazy(false); // Must be explicitly enabled. 757 set_allow_lazy(false); // Must be explicitly enabled.
758 set_allow_generators(FLAG_harmony_generators); 758 set_allow_generators(FLAG_harmony_generators);
759 set_allow_arrow_functions(FLAG_harmony_arrow_functions); 759 set_allow_arrow_functions(FLAG_harmony_arrow_functions);
760 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); 760 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
761 set_allow_classes(FLAG_harmony_classes); 761 set_allow_classes(FLAG_harmony_classes);
762 set_allow_harmony_object_literals(FLAG_harmony_object_literals); 762 set_allow_harmony_object_literals(FLAG_harmony_object_literals);
763 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; 763 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
(...skipping 27 matching lines...) Expand all
791 CompleteParserRecorder recorder; 791 CompleteParserRecorder recorder;
792 792
793 if (compile_options() == ScriptCompiler::kProduceParserCache) { 793 if (compile_options() == ScriptCompiler::kProduceParserCache) {
794 log_ = &recorder; 794 log_ = &recorder;
795 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) { 795 } else if (compile_options() == ScriptCompiler::kConsumeParserCache) {
796 cached_parse_data_->Initialize(); 796 cached_parse_data_->Initialize();
797 } 797 }
798 798
799 source = String::Flatten(source); 799 source = String::Flatten(source);
800 FunctionLiteral* result; 800 FunctionLiteral* result;
801
802 Scope* top_scope = NULL;
803 Scope* eval_scope = NULL;
801 if (source->IsExternalTwoByteString()) { 804 if (source->IsExternalTwoByteString()) {
802 // Notice that the stream is destroyed at the end of the branch block. 805 // Notice that the stream is destroyed at the end of the branch block.
803 // The last line of the blocks can't be moved outside, even though they're 806 // The last line of the blocks can't be moved outside, even though they're
804 // identical calls. 807 // identical calls.
805 ExternalTwoByteStringUtf16CharacterStream stream( 808 ExternalTwoByteStringUtf16CharacterStream stream(
806 Handle<ExternalTwoByteString>::cast(source), 0, source->length()); 809 Handle<ExternalTwoByteString>::cast(source), 0, source->length());
807 scanner_.Initialize(&stream); 810 scanner_.Initialize(&stream);
808 result = DoParseProgram(info(), source); 811 result = DoParseProgram(info(), &top_scope, &eval_scope);
809 } else { 812 } else {
810 GenericStringUtf16CharacterStream stream(source, 0, source->length()); 813 GenericStringUtf16CharacterStream stream(source, 0, source->length());
811 scanner_.Initialize(&stream); 814 scanner_.Initialize(&stream);
812 result = DoParseProgram(info(), source); 815 result = DoParseProgram(info(), &top_scope, &eval_scope);
816 }
817 top_scope->set_end_position(source->length());
818 if (eval_scope != NULL) {
819 eval_scope->set_end_position(source->length());
813 } 820 }
814 HandleSourceURLComments(); 821 HandleSourceURLComments();
815 822
816 if (FLAG_trace_parse && result != NULL) { 823 if (FLAG_trace_parse && result != NULL) {
817 double ms = timer.Elapsed().InMillisecondsF(); 824 double ms = timer.Elapsed().InMillisecondsF();
818 if (info()->is_eval()) { 825 if (info()->is_eval()) {
819 PrintF("[parsing eval"); 826 PrintF("[parsing eval");
820 } else if (info()->script()->name()->IsString()) { 827 } else if (info()->script()->name()->IsString()) {
821 String* name = String::cast(info()->script()->name()); 828 String* name = String::cast(info()->script()->name());
822 SmartArrayPointer<char> name_chars = name->ToCString(); 829 SmartArrayPointer<char> name_chars = name->ToCString();
823 PrintF("[parsing script: %s", name_chars.get()); 830 PrintF("[parsing script: %s", name_chars.get());
824 } else { 831 } else {
825 PrintF("[parsing script"); 832 PrintF("[parsing script");
826 } 833 }
827 PrintF(" - took %0.3f ms]\n", ms); 834 PrintF(" - took %0.3f ms]\n", ms);
828 } 835 }
829 if (compile_options() == ScriptCompiler::kProduceParserCache) { 836 if (compile_options() == ScriptCompiler::kProduceParserCache) {
830 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 837 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
831 log_ = NULL; 838 log_ = NULL;
832 } 839 }
833 return result; 840 return result;
834 } 841 }
835 842
836 843
837 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, 844 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
838 Handle<String> source) { 845 Scope** eval_scope) {
839 DCHECK(scope_ == NULL); 846 DCHECK(scope_ == NULL);
840 DCHECK(target_stack_ == NULL); 847 DCHECK(target_stack_ == NULL);
841 848
842 FunctionLiteral* result = NULL; 849 FunctionLiteral* result = NULL;
843 { Scope* scope = NewScope(scope_, GLOBAL_SCOPE); 850 {
844 info->SetGlobalScope(scope); 851 *scope = NewScope(scope_, GLOBAL_SCOPE);
852 info->SetGlobalScope(*scope);
845 if (!info->context().is_null() && !info->context()->IsNativeContext()) { 853 if (!info->context().is_null() && !info->context()->IsNativeContext()) {
846 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); 854 *scope = Scope::DeserializeScopeChain(*info->context(), *scope, zone());
847 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this 855 // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
848 // means the Parser cannot operate independent of the V8 heap. Tell the 856 // means the Parser cannot operate independent of the V8 heap. Tell the
849 // string table to internalize strings and values right after they're 857 // string table to internalize strings and values right after they're
850 // created. 858 // created.
851 ast_value_factory()->Internalize(isolate()); 859 ast_value_factory()->Internalize(isolate());
852 } 860 }
853 original_scope_ = scope; 861 original_scope_ = *scope;
854 if (info->is_eval()) { 862 if (info->is_eval()) {
855 if (!scope->is_global_scope() || info->strict_mode() == STRICT) { 863 if (!(*scope)->is_global_scope() || info->strict_mode() == STRICT) {
856 scope = NewScope(scope, EVAL_SCOPE); 864 *scope = NewScope(*scope, EVAL_SCOPE);
857 } 865 }
858 } else if (info->is_global()) { 866 } else if (info->is_global()) {
859 scope = NewScope(scope, GLOBAL_SCOPE); 867 *scope = NewScope(*scope, GLOBAL_SCOPE);
860 } 868 }
861 scope->set_start_position(0); 869 (*scope)->set_start_position(0);
862 scope->set_end_position(source->length()); 870 // End position will be set by the caller.
863 871
864 // Compute the parsing mode. 872 // Compute the parsing mode.
865 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY; 873 Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
866 if (allow_natives_syntax() || 874 if (allow_natives_syntax() || extension_ != NULL ||
867 extension_ != NULL || 875 (*scope)->is_eval_scope()) {
868 scope->is_eval_scope()) {
869 mode = PARSE_EAGERLY; 876 mode = PARSE_EAGERLY;
870 } 877 }
871 ParsingModeScope parsing_mode(this, mode); 878 ParsingModeScope parsing_mode(this, mode);
872 879
873 // Enters 'scope'. 880 // Enters 'scope'.
874 FunctionState function_state(&function_state_, &scope_, scope, zone(), 881 FunctionState function_state(&function_state_, &scope_, *scope, zone(),
875 ast_value_factory(), info->ast_node_id_gen()); 882 ast_value_factory(), info->ast_node_id_gen());
876 883
877 scope_->SetStrictMode(info->strict_mode()); 884 scope_->SetStrictMode(info->strict_mode());
878 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); 885 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
879 bool ok = true; 886 bool ok = true;
880 int beg_pos = scanner()->location().beg_pos; 887 int beg_pos = scanner()->location().beg_pos;
881 ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok); 888 ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope,
889 &ok);
882 890
883 if (ok && strict_mode() == STRICT) { 891 if (ok && strict_mode() == STRICT) {
884 CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); 892 CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
885 } 893 }
886 894
887 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) { 895 if (ok && allow_harmony_scoping() && strict_mode() == STRICT) {
888 CheckConflictingVarDeclarations(scope_, &ok); 896 CheckConflictingVarDeclarations(scope_, &ok);
889 } 897 }
890 898
891 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) { 899 if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 1024
1017 if (result != NULL) { 1025 if (result != NULL) {
1018 Handle<String> inferred_name(shared_info->inferred_name()); 1026 Handle<String> inferred_name(shared_info->inferred_name());
1019 result->set_inferred_name(inferred_name); 1027 result->set_inferred_name(inferred_name);
1020 } 1028 }
1021 return result; 1029 return result;
1022 } 1030 }
1023 1031
1024 1032
1025 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, 1033 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
1026 int end_token, 1034 int end_token, bool is_eval, bool is_global,
1027 bool is_eval, 1035 Scope** eval_scope, bool* ok) {
1028 bool is_global,
1029 bool* ok) {
1030 // SourceElements :: 1036 // SourceElements ::
1031 // (ModuleElement)* <end_token> 1037 // (ModuleElement)* <end_token>
1032 1038
1033 // Allocate a target stack to use for this set of source 1039 // Allocate a target stack to use for this set of source
1034 // elements. This way, all scripts and functions get their own 1040 // elements. This way, all scripts and functions get their own
1035 // target stack thus avoiding illegal breaks and continues across 1041 // target stack thus avoiding illegal breaks and continues across
1036 // functions. 1042 // functions.
1037 TargetScope scope(&this->target_stack_); 1043 TargetScope scope(&this->target_stack_);
1038 1044
1039 DCHECK(processor != NULL); 1045 DCHECK(processor != NULL);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 // as specified in ES5 10.4.2(3). The correct fix would be to always 1081 // as specified in ES5 10.4.2(3). The correct fix would be to always
1076 // add this scope in DoParseProgram(), but that requires adaptations 1082 // add this scope in DoParseProgram(), but that requires adaptations
1077 // all over the code base, so we go with a quick-fix for now. 1083 // all over the code base, so we go with a quick-fix for now.
1078 // In the same manner, we have to patch the parsing mode. 1084 // In the same manner, we have to patch the parsing mode.
1079 if (is_eval && !scope_->is_eval_scope()) { 1085 if (is_eval && !scope_->is_eval_scope()) {
1080 DCHECK(scope_->is_global_scope()); 1086 DCHECK(scope_->is_global_scope());
1081 Scope* scope = NewScope(scope_, EVAL_SCOPE); 1087 Scope* scope = NewScope(scope_, EVAL_SCOPE);
1082 scope->set_start_position(scope_->start_position()); 1088 scope->set_start_position(scope_->start_position());
1083 scope->set_end_position(scope_->end_position()); 1089 scope->set_end_position(scope_->end_position());
1084 scope_ = scope; 1090 scope_ = scope;
1091 if (eval_scope != NULL) {
1092 // Caller will correct the positions of the ad hoc eval scope.
1093 *eval_scope = scope;
1094 }
1085 mode_ = PARSE_EAGERLY; 1095 mode_ = PARSE_EAGERLY;
1086 } 1096 }
1087 scope_->SetStrictMode(STRICT); 1097 scope_->SetStrictMode(STRICT);
1088 // "use strict" is the only directive for now. 1098 // "use strict" is the only directive for now.
1089 directive_prologue = false; 1099 directive_prologue = false;
1090 } else if (literal->raw_value()->AsString() == 1100 } else if (literal->raw_value()->AsString() ==
1091 ast_value_factory()->use_asm_string() && 1101 ast_value_factory()->use_asm_string() &&
1092 token_loc.end_pos - token_loc.beg_pos == 1102 token_loc.end_pos - token_loc.beg_pos ==
1093 ast_value_factory()->use_asm_string()->length() + 2) { 1103 ast_value_factory()->use_asm_string()->length() + 2) {
1094 // Store the usage count; The actual use counter on the isolate is 1104 // Store the usage count; The actual use counter on the isolate is
(...skipping 2620 matching lines...) Expand 10 before | Expand all | Expand 10 after
3715 Assignment* assignment = factory()->NewAssignment( 3725 Assignment* assignment = factory()->NewAssignment(
3716 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition); 3726 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3717 VariableProxy* get_proxy = factory()->NewVariableProxy( 3727 VariableProxy* get_proxy = factory()->NewVariableProxy(
3718 function_state_->generator_object_variable()); 3728 function_state_->generator_object_variable());
3719 Yield* yield = factory()->NewYield( 3729 Yield* yield = factory()->NewYield(
3720 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition); 3730 get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
3721 body->Add(factory()->NewExpressionStatement( 3731 body->Add(factory()->NewExpressionStatement(
3722 yield, RelocInfo::kNoPosition), zone()); 3732 yield, RelocInfo::kNoPosition), zone());
3723 } 3733 }
3724 3734
3725 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK); 3735 ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK);
3726 3736
3727 if (is_generator) { 3737 if (is_generator) {
3728 VariableProxy* get_proxy = factory()->NewVariableProxy( 3738 VariableProxy* get_proxy = factory()->NewVariableProxy(
3729 function_state_->generator_object_variable()); 3739 function_state_->generator_object_variable());
3730 Expression* undefined = 3740 Expression* undefined =
3731 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition); 3741 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
3732 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal, 3742 Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
3733 RelocInfo::kNoPosition); 3743 RelocInfo::kNoPosition);
3734 body->Add(factory()->NewExpressionStatement( 3744 body->Add(factory()->NewExpressionStatement(
3735 yield, RelocInfo::kNoPosition), zone()); 3745 yield, RelocInfo::kNoPosition), zone());
(...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after
4832 SetCachedData(); 4842 SetCachedData();
4833 result = ParseProgram(); 4843 result = ParseProgram();
4834 } 4844 }
4835 info()->SetFunction(result); 4845 info()->SetFunction(result);
4836 4846
4837 Internalize(); 4847 Internalize();
4838 DCHECK(ast_value_factory()->IsInternalized()); 4848 DCHECK(ast_value_factory()->IsInternalized());
4839 return (result != NULL); 4849 return (result != NULL);
4840 } 4850 }
4841 4851
4852
4853 void Parser::ParseOnBackground() {
4854 DCHECK(info()->function() == NULL);
4855 FunctionLiteral* result = NULL;
4856 fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
4857
4858 CompleteParserRecorder recorder;
4859 if (compile_options() == ScriptCompiler::kProduceParserCache) {
4860 log_ = &recorder;
4861 }
4862
4863 DCHECK(info()->source_stream() != NULL);
4864 ExternalStreamingStream stream(info()->source_stream(),
4865 info()->source_stream_encoding());
4866 scanner_.Initialize(&stream);
4867 DCHECK(info()->context().is_null() || info()->context()->IsNativeContext());
4868
4869 // When streaming, we don't know the length of the source until we have parsed
4870 // it. The raw data can be UTF-8, so we wouldn't know the source length until
4871 // we have decoded it anyway even if we knew the raw data length (which we
4872 // don't). We work around this by storing all the scopes which need their end
4873 // position set at the end of the script (the top scope and possible eval
4874 // scopes) and set their end position after we know the script length.
4875 Scope* top_scope = NULL;
4876 Scope* eval_scope = NULL;
4877 result = DoParseProgram(info(), &top_scope, &eval_scope);
4878
4879 top_scope->set_end_position(scanner()->location().end_pos);
4880 if (eval_scope != NULL) {
4881 eval_scope->set_end_position(scanner()->location().end_pos);
4882 }
4883
4884 info()->SetFunction(result);
4885
4886 // We cannot internalize on a background thread; a foreground task will take
4887 // care of calling Parser::Internalize just before compilation.
4888
4889 if (compile_options() == ScriptCompiler::kProduceParserCache) {
4890 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4891 log_ = NULL;
4892 }
4893 }
4842 } } // namespace v8::internal 4894 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/scanner-character-streams.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698