| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 62e9cbad77662d9b306760a893aea2655ddf6fb9..01bd85348f5744bae34f0f93f7e3c7fb1e76973c 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -205,19 +205,6 @@ void RegExpBuilder::AddQuantifierToAtom(
|
| }
|
|
|
|
|
| -Handle<String> Parser::LookupSymbol(int symbol_id) {
|
| - // If there is no preparser symbol data, a negative number will be passed. In
|
| - // that case, we'll just read the literal from Scanner. This also guards
|
| - // against corrupt preparse data where the symbol id is larger than the symbol
|
| - // count.
|
| - if (symbol_id < 0 ||
|
| - (pre_parse_data_ && symbol_id >= pre_parse_data_->symbol_count())) {
|
| - return scanner()->AllocateInternalizedString(isolate_);
|
| - }
|
| - return LookupCachedSymbol(symbol_id);
|
| -}
|
| -
|
| -
|
| Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
|
| // Make sure the cache is large enough to hold the symbol identifier.
|
| if (symbol_cache_.length() <= symbol_id) {
|
| @@ -600,11 +587,19 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
|
|
|
|
| Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
|
| - int symbol_id = -1;
|
| - if (parser_->pre_parse_data() != NULL) {
|
| - symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
|
| + if (parser_->cached_data_mode() == CONSUME_CACHED_DATA) {
|
| + int symbol_id = (*parser_->cached_data())->GetSymbolIdentifier();
|
| + // If there is no symbol data, -1 will be returned.
|
| + if (symbol_id >= 0 &&
|
| + symbol_id < (*parser_->cached_data())->symbol_count()) {
|
| + return parser_->LookupCachedSymbol(symbol_id);
|
| + }
|
| + } else if (parser_->cached_data_mode() == PRODUCE_CACHED_DATA) {
|
| + if (parser_->log_->ShouldLogSymbols()) {
|
| + parser_->scanner()->LogSymbol(parser_->log_, parser_->position());
|
| + }
|
| }
|
| - return parser_->LookupSymbol(symbol_id);
|
| + return parser_->scanner()->AllocateInternalizedString(parser_->isolate_);
|
| }
|
|
|
|
|
| @@ -702,6 +697,7 @@ Parser::Parser(CompilationInfo* info)
|
| : ParserBase<ParserTraits>(&scanner_,
|
| info->isolate()->stack_guard()->real_climit(),
|
| info->extension(),
|
| + NULL,
|
| info->zone(),
|
| this),
|
| isolate_(info->isolate()),
|
| @@ -711,7 +707,8 @@ Parser::Parser(CompilationInfo* info)
|
| reusable_preparser_(NULL),
|
| original_scope_(NULL),
|
| target_stack_(NULL),
|
| - pre_parse_data_(NULL),
|
| + cached_data_(NULL),
|
| + cached_data_mode_(NO_CACHED_DATA),
|
| info_(info) {
|
| ASSERT(!script_.is_null());
|
| isolate_->set_ast_node_id(0);
|
| @@ -738,6 +735,13 @@ FunctionLiteral* Parser::ParseProgram() {
|
| fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
|
|
|
| // Initialize parser state.
|
| + CompleteParserRecorder recorder;
|
| + if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| + log_ = &recorder;
|
| + } else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
|
| + (*cached_data_)->Initialize();
|
| + }
|
| +
|
| source->TryFlatten();
|
| FunctionLiteral* result;
|
| if (source->IsExternalTwoByteString()) {
|
| @@ -767,6 +771,11 @@ FunctionLiteral* Parser::ParseProgram() {
|
| }
|
| PrintF(" - took %0.3f ms]\n", ms);
|
| }
|
| + if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| + Vector<unsigned> store = recorder.ExtractData();
|
| + *cached_data_ = new ScriptDataImpl(store);
|
| + log_ = NULL;
|
| + }
|
| return result;
|
| }
|
|
|
| @@ -775,7 +784,6 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| Handle<String> source) {
|
| ASSERT(scope_ == NULL);
|
| ASSERT(target_stack_ == NULL);
|
| - if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
|
|
|
| Handle<String> no_name = isolate()->factory()->empty_string();
|
|
|
| @@ -3580,11 +3588,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| if (is_lazily_parsed) {
|
| int function_block_pos = position();
|
| FunctionEntry entry;
|
| - if (pre_parse_data_ != NULL) {
|
| - // If we have pre_parse_data_, we use it to skip parsing the function
|
| - // body. The preparser data contains the information we need to
|
| - // construct the lazy function.
|
| - entry = pre_parse_data()->GetFunctionEntry(function_block_pos);
|
| + if (cached_data_mode_ == CONSUME_CACHED_DATA) {
|
| + // If we have cached data, we use it to skip parsing the function body.
|
| + // The data contains the information we need to construct the lazy
|
| + // function.
|
| + entry = (*cached_data())->GetFunctionEntry(function_block_pos);
|
| if (entry.is_valid()) {
|
| if (entry.end_pos() <= function_block_pos) {
|
| // End position greater than end of stream is safe, and hard
|
| @@ -3605,21 +3613,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // an entry for the function. As a safety net, fall back to eager
|
| // parsing. It is unclear whether PreParser's laziness analysis can
|
| // produce different results than the Parser's laziness analysis (see
|
| - // https://codereview.chromium.org/7565003 ). This safety net is
|
| - // guarding against the case where Parser thinks a function should be
|
| - // lazily parsed, but PreParser thinks it should be eagerly parsed --
|
| - // in that case we fall back to eager parsing in Parser, too. Note
|
| - // that the opposite case is worse: if PreParser thinks a function
|
| - // should be lazily parsed, but Parser thinks it should be eagerly
|
| - // parsed, it will never advance the preparse data beyond that
|
| - // function and all further laziness will fail (all functions will be
|
| - // parsed eagerly).
|
| + // https://codereview.chromium.org/7565003 ). In this case, we must
|
| + // discard all the preparse data, since the symbol data will be wrong.
|
| is_lazily_parsed = false;
|
| + cached_data_mode_ = NO_CACHED_DATA;
|
| }
|
| } else {
|
| - // With no preparser data, we partially parse the function, without
|
| + // With no cached data, we partially parse the function, without
|
| // building an AST. This gathers the data needed to build a lazy
|
| // function.
|
| + // FIXME(marja): Now the PreParser doesn't need to log functions /
|
| + // symbols; only errors -> clean that up.
|
| SingletonLogger logger;
|
| PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
|
| if (result == PreParser::kPreParseStackOverflow) {
|
| @@ -3648,6 +3652,15 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| materialized_literal_count = logger.literals();
|
| expected_property_count = logger.properties();
|
| scope_->SetStrictMode(logger.strict_mode());
|
| + if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| + ASSERT(log_);
|
| + // Position right after terminal '}'.
|
| + int body_end = scanner()->location().end_pos;
|
| + log_->LogFunction(function_block_pos, body_end,
|
| + materialized_literal_count,
|
| + expected_property_count,
|
| + scope_->strict_mode());
|
| + }
|
| }
|
| }
|
|
|
| @@ -4922,12 +4935,13 @@ bool Parser::Parse() {
|
| result = ParseProgram();
|
| }
|
| } else {
|
| - ScriptDataImpl* pre_parse_data = info()->pre_parse_data();
|
| - set_pre_parse_data(pre_parse_data);
|
| - if (pre_parse_data != NULL && pre_parse_data->has_error()) {
|
| - Scanner::Location loc = pre_parse_data->MessageLocation();
|
| - const char* message = pre_parse_data->BuildMessage();
|
| - Vector<const char*> args = pre_parse_data->BuildArgs();
|
| + SetCachedData(info()->cached_data(), info()->cached_data_mode());
|
| + if (info()->cached_data_mode() == CONSUME_CACHED_DATA &&
|
| + (*info()->cached_data())->has_error()) {
|
| + ScriptDataImpl* cached_data = *(info()->cached_data());
|
| + Scanner::Location loc = cached_data->MessageLocation();
|
| + const char* message = cached_data->BuildMessage();
|
| + Vector<const char*> args = cached_data->BuildArgs();
|
| ParserTraits::ReportMessageAt(loc, message, args);
|
| DeleteArray(message);
|
| for (int i = 0; i < args.length(); i++) {
|
|
|