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

Side by Side Diff: src/parser.cc

Issue 181543003: Proof of concept: API for doing only one parsing pass instead of first preparsing and then parsing. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased -- this applies to r19832 Created 6 years, 9 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/preparser.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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone()); 203 new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
204 LAST(ADD_TERM); 204 LAST(ADD_TERM);
205 } 205 }
206 206
207 207
208 Handle<String> Parser::LookupSymbol(int symbol_id) { 208 Handle<String> Parser::LookupSymbol(int symbol_id) {
209 // If there is no preparser symbol data, a negative number will be passed. In 209 // If there is no preparser symbol data, a negative number will be passed. In
210 // that case, we'll just read the literal from Scanner. This also guards 210 // that case, we'll just read the literal from Scanner. This also guards
211 // against corrupt preparse data where the symbol id is larger than the symbol 211 // against corrupt preparse data where the symbol id is larger than the symbol
212 // count. 212 // count.
213 if (symbol_id < 0 || 213 if (symbol_id < 0 || (cached_data_ && *cached_data_ &&
214 (pre_parse_data_ && symbol_id >= pre_parse_data_->symbol_count())) { 214 symbol_id >= (*cached_data_)->symbol_count())) {
215 if (scanner()->is_literal_ascii()) { 215 if (scanner()->is_literal_ascii()) {
216 if (log_) {
217 log_->LogAsciiSymbol(position(), scanner()->literal_ascii_string());
218 }
216 return isolate()->factory()->InternalizeOneByteString( 219 return isolate()->factory()->InternalizeOneByteString(
217 Vector<const uint8_t>::cast(scanner()->literal_ascii_string())); 220 Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
221
218 } else { 222 } else {
223 if (log_) {
224 log_->LogUtf16Symbol(position(), scanner()->literal_utf16_string());
225 }
219 return isolate()->factory()->InternalizeTwoByteString( 226 return isolate()->factory()->InternalizeTwoByteString(
220 scanner()->literal_utf16_string()); 227 scanner()->literal_utf16_string());
221 } 228 }
222 } 229 }
223 return LookupCachedSymbol(symbol_id); 230 return LookupCachedSymbol(symbol_id);
224 } 231 }
225 232
226 233
227 Handle<String> Parser::LookupCachedSymbol(int symbol_id) { 234 Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
228 // Make sure the cache is large enough to hold the symbol identifier. 235 // Make sure the cache is large enough to hold the symbol identifier.
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 elements->set(i, *args[i]); 493 elements->set(i, *args[i]);
487 } 494 }
488 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); 495 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
489 Handle<Object> result = factory->NewSyntaxError(message, array); 496 Handle<Object> result = factory->NewSyntaxError(message, array);
490 parser_->isolate()->Throw(*result, &location); 497 parser_->isolate()->Throw(*result, &location);
491 } 498 }
492 499
493 500
494 Handle<String> ParserTraits::GetSymbol(Scanner* scanner) { 501 Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
495 int symbol_id = -1; 502 int symbol_id = -1;
496 if (parser_->pre_parse_data() != NULL) { 503 if (parser_->cached_data_ != NULL && *(parser_->cached_data_) != NULL) {
497 symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier(); 504 symbol_id = (*parser_->cached_data_)->GetSymbolIdentifier();
498 } 505 }
499 return parser_->LookupSymbol(symbol_id); 506 return parser_->LookupSymbol(symbol_id);
500 } 507 }
501 508
502 509
503 Handle<String> ParserTraits::NextLiteralString(Scanner* scanner, 510 Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
504 PretenureFlag tenured) { 511 PretenureFlag tenured) {
505 if (scanner->is_next_literal_ascii()) { 512 if (scanner->is_next_literal_ascii()) {
506 return parser_->isolate_->factory()->NewStringFromAscii( 513 return parser_->isolate_->factory()->NewStringFromAscii(
507 scanner->next_literal_ascii_string(), tenured); 514 scanner->next_literal_ascii_string(), tenured);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 return parser_->ParseFunctionLiteral(name, function_name_location, 604 return parser_->ParseFunctionLiteral(name, function_name_location,
598 name_is_strict_reserved, is_generator, 605 name_is_strict_reserved, is_generator,
599 function_token_position, type, ok); 606 function_token_position, type, ok);
600 } 607 }
601 608
602 609
603 Parser::Parser(CompilationInfo* info) 610 Parser::Parser(CompilationInfo* info)
604 : ParserBase<ParserTraits>(&scanner_, 611 : ParserBase<ParserTraits>(&scanner_,
605 info->isolate()->stack_guard()->real_climit(), 612 info->isolate()->stack_guard()->real_climit(),
606 info->extension(), 613 info->extension(),
614 NULL,
607 info->zone(), 615 info->zone(),
608 this), 616 this),
609 isolate_(info->isolate()), 617 isolate_(info->isolate()),
610 symbol_cache_(0, info->zone()), 618 symbol_cache_(0, info->zone()),
611 script_(info->script()), 619 script_(info->script()),
612 scanner_(isolate_->unicode_cache()), 620 scanner_(isolate_->unicode_cache()),
613 reusable_preparser_(NULL), 621 reusable_preparser_(NULL),
614 original_scope_(NULL), 622 original_scope_(NULL),
615 target_stack_(NULL), 623 target_stack_(NULL),
616 pre_parse_data_(NULL), 624 cached_data_(NULL),
617 info_(info) { 625 info_(info) {
618 ASSERT(!script_.is_null()); 626 ASSERT(!script_.is_null());
619 isolate_->set_ast_node_id(0); 627 isolate_->set_ast_node_id(0);
620 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); 628 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
621 set_allow_modules(!info->is_native() && FLAG_harmony_modules); 629 set_allow_modules(!info->is_native() && FLAG_harmony_modules);
622 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); 630 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
623 set_allow_lazy(false); // Must be explicitly enabled. 631 set_allow_lazy(false); // Must be explicitly enabled.
624 set_allow_generators(FLAG_harmony_generators); 632 set_allow_generators(FLAG_harmony_generators);
625 set_allow_for_of(FLAG_harmony_iteration); 633 set_allow_for_of(FLAG_harmony_iteration);
626 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); 634 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
627 } 635 }
628 636
629 637
630 FunctionLiteral* Parser::ParseProgram() { 638 FunctionLiteral* Parser::ParseProgram() {
639 CompleteParserRecorder recorder;
640 if (cached_data_ != NULL && *cached_data_ == NULL) {
641 // We're asked to generate data to cache.
642 log_ = &recorder;
643 }
631 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here, 644 // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
632 // see comment for HistogramTimerScope class. 645 // see comment for HistogramTimerScope class.
633 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true); 646 HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
634 Handle<String> source(String::cast(script_->source())); 647 Handle<String> source(String::cast(script_->source()));
635 isolate()->counters()->total_parse_size()->Increment(source->length()); 648 isolate()->counters()->total_parse_size()->Increment(source->length());
636 ElapsedTimer timer; 649 ElapsedTimer timer;
637 if (FLAG_trace_parse) { 650 if (FLAG_trace_parse) {
638 timer.Start(); 651 timer.Start();
639 } 652 }
640 fni_ = new(zone()) FuncNameInferrer(isolate(), zone()); 653 fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
(...skipping 21 matching lines...) Expand all
662 PrintF("[parsing eval"); 675 PrintF("[parsing eval");
663 } else if (info()->script()->name()->IsString()) { 676 } else if (info()->script()->name()->IsString()) {
664 String* name = String::cast(info()->script()->name()); 677 String* name = String::cast(info()->script()->name());
665 SmartArrayPointer<char> name_chars = name->ToCString(); 678 SmartArrayPointer<char> name_chars = name->ToCString();
666 PrintF("[parsing script: %s", name_chars.get()); 679 PrintF("[parsing script: %s", name_chars.get());
667 } else { 680 } else {
668 PrintF("[parsing script"); 681 PrintF("[parsing script");
669 } 682 }
670 PrintF(" - took %0.3f ms]\n", ms); 683 PrintF(" - took %0.3f ms]\n", ms);
671 } 684 }
685 if (cached_data_ != NULL && *cached_data_ == NULL) {
686 Vector<unsigned> store = recorder.ExtractData();
687 *cached_data_ = new ScriptDataImpl(store);
688 log_ = NULL;
689 }
672 return result; 690 return result;
673 } 691 }
674 692
675 693
676 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, 694 FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
677 Handle<String> source) { 695 Handle<String> source) {
678 ASSERT(scope_ == NULL); 696 ASSERT(scope_ == NULL);
679 ASSERT(target_stack_ == NULL); 697 ASSERT(target_stack_ == NULL);
680 if (pre_parse_data_ != NULL) pre_parse_data_->Initialize(); 698 if (cached_data_ != NULL && *cached_data_ != NULL) {
699 (*cached_data_)->Initialize();
700 }
681 701
682 Handle<String> no_name = isolate()->factory()->empty_string(); 702 Handle<String> no_name = isolate()->factory()->empty_string();
683 703
684 FunctionLiteral* result = NULL; 704 FunctionLiteral* result = NULL;
685 { Scope* scope = NewScope(scope_, GLOBAL_SCOPE); 705 { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
686 info->SetGlobalScope(scope); 706 info->SetGlobalScope(scope);
687 if (!info->context().is_null()) { 707 if (!info->context().is_null()) {
688 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); 708 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
689 } 709 }
690 original_scope_ = scope; 710 original_scope_ = scope;
(...skipping 3098 matching lines...) Expand 10 before | Expand all | Expand 10 after
3789 // To make this additional case work, both Parser and PreParser implement a 3809 // To make this additional case work, both Parser and PreParser implement a
3790 // logic where only top-level functions will be parsed lazily. 3810 // logic where only top-level functions will be parsed lazily.
3791 bool is_lazily_parsed = (mode() == PARSE_LAZILY && 3811 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3792 scope_->AllowsLazyCompilation() && 3812 scope_->AllowsLazyCompilation() &&
3793 !parenthesized_function_); 3813 !parenthesized_function_);
3794 parenthesized_function_ = false; // The bit was set for this function only. 3814 parenthesized_function_ = false; // The bit was set for this function only.
3795 3815
3796 if (is_lazily_parsed) { 3816 if (is_lazily_parsed) {
3797 int function_block_pos = position(); 3817 int function_block_pos = position();
3798 FunctionEntry entry; 3818 FunctionEntry entry;
3799 if (pre_parse_data_ != NULL) { 3819 if (cached_data_ != NULL && *cached_data_ != NULL) {
3800 // If we have pre_parse_data_, we use it to skip parsing the function 3820 // If we have cached_data_, we use it to skip parsing the function
3801 // body. The preparser data contains the information we need to 3821 // body. The data contains the information we need to
3802 // construct the lazy function. 3822 // construct the lazy function.
3803 entry = pre_parse_data()->GetFunctionEntry(function_block_pos); 3823 entry = (*cached_data_)->GetFunctionEntry(function_block_pos);
3804 if (entry.is_valid()) { 3824 if (entry.is_valid()) {
3805 if (entry.end_pos() <= function_block_pos) { 3825 if (entry.end_pos() <= function_block_pos) {
3806 // End position greater than end of stream is safe, and hard 3826 // End position greater than end of stream is safe, and hard
3807 // to check. 3827 // to check.
3808 ReportInvalidPreparseData(function_name, CHECK_OK); 3828 ReportInvalidPreparseData(function_name, CHECK_OK);
3809 } 3829 }
3810 scanner()->SeekForward(entry.end_pos() - 1); 3830 scanner()->SeekForward(entry.end_pos() - 1);
3811 3831
3812 scope->set_end_position(entry.end_pos()); 3832 scope->set_end_position(entry.end_pos());
3813 Expect(Token::RBRACE, CHECK_OK); 3833 Expect(Token::RBRACE, CHECK_OK);
(...skipping 12 matching lines...) Expand all
3826 // lazily parsed, but PreParser thinks it should be eagerly parsed -- 3846 // lazily parsed, but PreParser thinks it should be eagerly parsed --
3827 // in that case we fall back to eager parsing in Parser, too. Note 3847 // in that case we fall back to eager parsing in Parser, too. Note
3828 // that the opposite case is worse: if PreParser thinks a function 3848 // that the opposite case is worse: if PreParser thinks a function
3829 // should be lazily parsed, but Parser thinks it should be eagerly 3849 // should be lazily parsed, but Parser thinks it should be eagerly
3830 // parsed, it will never advance the preparse data beyond that 3850 // parsed, it will never advance the preparse data beyond that
3831 // function and all further laziness will fail (all functions will be 3851 // function and all further laziness will fail (all functions will be
3832 // parsed eagerly). 3852 // parsed eagerly).
3833 is_lazily_parsed = false; 3853 is_lazily_parsed = false;
3834 } 3854 }
3835 } else { 3855 } else {
3856 if (log_) log_->PauseRecording();
3836 // With no preparser data, we partially parse the function, without 3857 // With no preparser data, we partially parse the function, without
3837 // building an AST. This gathers the data needed to build a lazy 3858 // building an AST. This gathers the data needed to build a lazy
3838 // function. 3859 // function.
3839 SingletonLogger logger; 3860 SingletonLogger logger;
3840 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); 3861 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
3841 if (result == PreParser::kPreParseStackOverflow) { 3862 if (result == PreParser::kPreParseStackOverflow) {
3842 // Propagate stack overflow. 3863 // Propagate stack overflow.
3843 set_stack_overflow(); 3864 set_stack_overflow();
3844 *ok = false; 3865 *ok = false;
3845 return NULL; 3866 return NULL;
(...skipping 11 matching lines...) Expand all
3857 *ok = false; 3878 *ok = false;
3858 return NULL; 3879 return NULL;
3859 } 3880 }
3860 scope->set_end_position(logger.end()); 3881 scope->set_end_position(logger.end());
3861 Expect(Token::RBRACE, CHECK_OK); 3882 Expect(Token::RBRACE, CHECK_OK);
3862 isolate()->counters()->total_preparse_skipped()->Increment( 3883 isolate()->counters()->total_preparse_skipped()->Increment(
3863 scope->end_position() - function_block_pos); 3884 scope->end_position() - function_block_pos);
3864 materialized_literal_count = logger.literals(); 3885 materialized_literal_count = logger.literals();
3865 expected_property_count = logger.properties(); 3886 expected_property_count = logger.properties();
3866 scope_->SetStrictMode(logger.strict_mode()); 3887 scope_->SetStrictMode(logger.strict_mode());
3888 if (log_) {
3889 log_->ResumeRecording();
3890 // Position right after terminal '}'.
3891 int body_end = scanner()->location().end_pos;
3892 log_->LogFunction(function_block_pos, body_end,
3893 materialized_literal_count,
3894 expected_property_count,
3895 scope_->strict_mode());
3896 }
3867 } 3897 }
3868 } 3898 }
3869 3899
3870 if (!is_lazily_parsed) { 3900 if (!is_lazily_parsed) {
3871 // Everything inside an eagerly parsed function will be parsed eagerly 3901 // Everything inside an eagerly parsed function will be parsed eagerly
3872 // (see comment above). 3902 // (see comment above).
3873 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 3903 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3874 body = new(zone()) ZoneList<Statement*>(8, zone()); 3904 body = new(zone()) ZoneList<Statement*>(8, zone());
3875 if (fvar != NULL) { 3905 if (fvar != NULL) {
3876 VariableProxy* fproxy = scope_->NewUnresolved( 3906 VariableProxy* fproxy = scope_->NewUnresolved(
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after
5156 ASSERT(info()->function() == NULL); 5186 ASSERT(info()->function() == NULL);
5157 FunctionLiteral* result = NULL; 5187 FunctionLiteral* result = NULL;
5158 if (info()->is_lazy()) { 5188 if (info()->is_lazy()) {
5159 ASSERT(!info()->is_eval()); 5189 ASSERT(!info()->is_eval());
5160 if (info()->shared_info()->is_function()) { 5190 if (info()->shared_info()->is_function()) {
5161 result = ParseLazy(); 5191 result = ParseLazy();
5162 } else { 5192 } else {
5163 result = ParseProgram(); 5193 result = ParseProgram();
5164 } 5194 }
5165 } else { 5195 } else {
5166 ScriptDataImpl* pre_parse_data = info()->pre_parse_data(); 5196 ScriptDataImpl** cached_data = info()->cached_data();
5167 set_pre_parse_data(pre_parse_data); 5197 set_cached_data(cached_data);
5168 if (pre_parse_data != NULL && pre_parse_data->has_error()) { 5198 if (cached_data != NULL && *cached_data != NULL &&
5169 Scanner::Location loc = pre_parse_data->MessageLocation(); 5199 (*cached_data)->has_error()) {
5170 const char* message = pre_parse_data->BuildMessage(); 5200 Scanner::Location loc = (*cached_data)->MessageLocation();
5171 Vector<const char*> args = pre_parse_data->BuildArgs(); 5201 const char* message = (*cached_data)->BuildMessage();
5202 Vector<const char*> args = (*cached_data)->BuildArgs();
5172 ParserTraits::ReportMessageAt(loc, message, args); 5203 ParserTraits::ReportMessageAt(loc, message, args);
5173 DeleteArray(message); 5204 DeleteArray(message);
5174 for (int i = 0; i < args.length(); i++) { 5205 for (int i = 0; i < args.length(); i++) {
5175 DeleteArray(args[i]); 5206 DeleteArray(args[i]);
5176 } 5207 }
5177 DeleteArray(args.start()); 5208 DeleteArray(args.start());
5178 ASSERT(info()->isolate()->has_pending_exception()); 5209 ASSERT(info()->isolate()->has_pending_exception());
5179 } else { 5210 } else {
5180 result = ParseProgram(); 5211 result = ParseProgram();
5181 } 5212 }
5182 } 5213 }
5183 info()->SetFunction(result); 5214 info()->SetFunction(result);
5184 return (result != NULL); 5215 return (result != NULL);
5185 } 5216 }
5186 5217
5187 } } // namespace v8::internal 5218 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698