| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |