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

Side by Side Diff: src/parser.cc

Issue 169223009: Add comments about lazy parsing and lazy compilation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 6 years, 10 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 | « no previous file | src/preparser.cc » ('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 3955 matching lines...) Expand 10 before | Expand all | Expand 10 after
3966 VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST; 3966 VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
3967 fvar = new(zone()) Variable(scope_, 3967 fvar = new(zone()) Variable(scope_,
3968 function_name, fvar_mode, true /* is valid LHS */, 3968 function_name, fvar_mode, true /* is valid LHS */,
3969 Variable::NORMAL, kCreatedInitialized, Interface::NewConst()); 3969 Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
3970 VariableProxy* proxy = factory()->NewVariableProxy(fvar); 3970 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3971 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( 3971 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3972 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); 3972 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3973 scope_->DeclareFunctionVar(fvar_declaration); 3973 scope_->DeclareFunctionVar(fvar_declaration);
3974 } 3974 }
3975 3975
3976 // Determine whether the function will be lazily compiled. 3976 // Determine if the function can be parsed lazily. Lazy parsing is different
3977 // The heuristics are: 3977 // from lazy compilation; we need to parse more eagerly than we compile.
3978
3979 // We can only parse lazily if we also compile lazily. The heuristics for
3980 // lazy compilation are:
3978 // - It must not have been prohibited by the caller to Parse (some callers 3981 // - It must not have been prohibited by the caller to Parse (some callers
3979 // need a full AST). 3982 // need a full AST).
3980 // - The outer scope must allow lazy compilation of inner functions. 3983 // - The outer scope must allow lazy compilation of inner functions.
3981 // - The function mustn't be a function expression with an open parenthesis 3984 // - The function mustn't be a function expression with an open parenthesis
3982 // before; we consider that a hint that the function will be called 3985 // before; we consider that a hint that the function will be called
3983 // immediately, and it would be a waste of time to make it lazily 3986 // immediately, and it would be a waste of time to make it lazily
3984 // compiled. 3987 // compiled.
3985 // These are all things we can know at this point, without looking at the 3988 // These are all things we can know at this point, without looking at the
3986 // function itself. 3989 // function itself.
3987 bool is_lazily_compiled = (mode() == PARSE_LAZILY && 3990
3988 scope_->AllowsLazyCompilation() && 3991 // In addition, we need to distinguish between these cases:
3989 !parenthesized_function_); 3992 // (function foo() {
3993 // bar = function() { return 1; }
3994 // })();
3995 // and
3996 // (function foo() {
3997 // var a = 1;
3998 // bar = function() { return a; }
3999 // })();
4000
4001 // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
4002 // parenthesis before the function means that it will be called
4003 // immediately). The inner function *must* be parsed eagerly to resolve the
4004 // possible reference to the variable in foo's scope. However, it's possible
4005 // that it will be compiled lazily.
4006
4007 // To make this additional case work, both Parser and PreParser implement a
4008 // logic where only top-level functions will be parsed lazily.
4009 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
4010 scope_->AllowsLazyCompilation() &&
4011 !parenthesized_function_);
3990 parenthesized_function_ = false; // The bit was set for this function only. 4012 parenthesized_function_ = false; // The bit was set for this function only.
3991 4013
3992 if (is_lazily_compiled) { 4014 if (is_lazily_parsed) {
3993 int function_block_pos = position(); 4015 int function_block_pos = position();
3994 FunctionEntry entry; 4016 FunctionEntry entry;
3995 if (pre_parse_data_ != NULL) { 4017 if (pre_parse_data_ != NULL) {
3996 // If we have pre_parse_data_, we use it to skip parsing the function 4018 // If we have pre_parse_data_, we use it to skip parsing the function
3997 // body. The preparser data contains the information we need to 4019 // body. The preparser data contains the information we need to
3998 // construct the lazy function. 4020 // construct the lazy function.
3999 entry = pre_parse_data()->GetFunctionEntry(function_block_pos); 4021 entry = pre_parse_data()->GetFunctionEntry(function_block_pos);
4000 if (entry.is_valid()) { 4022 if (entry.is_valid()) {
4001 if (entry.end_pos() <= function_block_pos) { 4023 if (entry.end_pos() <= function_block_pos) {
4002 // End position greater than end of stream is safe, and hard 4024 // End position greater than end of stream is safe, and hard
4003 // to check. 4025 // to check.
4004 ReportInvalidPreparseData(function_name, CHECK_OK); 4026 ReportInvalidPreparseData(function_name, CHECK_OK);
4005 } 4027 }
4006 scanner()->SeekForward(entry.end_pos() - 1); 4028 scanner()->SeekForward(entry.end_pos() - 1);
4007 4029
4008 scope->set_end_position(entry.end_pos()); 4030 scope->set_end_position(entry.end_pos());
4009 Expect(Token::RBRACE, CHECK_OK); 4031 Expect(Token::RBRACE, CHECK_OK);
4010 isolate()->counters()->total_preparse_skipped()->Increment( 4032 isolate()->counters()->total_preparse_skipped()->Increment(
4011 scope->end_position() - function_block_pos); 4033 scope->end_position() - function_block_pos);
4012 materialized_literal_count = entry.literal_count(); 4034 materialized_literal_count = entry.literal_count();
4013 expected_property_count = entry.property_count(); 4035 expected_property_count = entry.property_count();
4014 scope_->SetLanguageMode(entry.language_mode()); 4036 scope_->SetLanguageMode(entry.language_mode());
4015 } else { 4037 } else {
4016 is_lazily_compiled = false; 4038 // This case happens when we have preparse data but it doesn't contain
4039 // an entry for the function. As a safety net, fall back to eager
4040 // parsing. It is unclear whether PreParser's laziness analysis can
4041 // produce different results than the Parser's laziness analysis (see
4042 // https://codereview.chromium.org/7565003 ). This safety net is
4043 // guarding against the case where Parser thinks a function should be
4044 // lazily parsed, but PreParser thinks it should be eagerly parsed --
4045 // in that case we fall back to eager parsing in Parser, too. Note
4046 // that the opposite case is worse: if PreParser thinks a function
4047 // should be lazily parsed, but Parser thinks it should be eagerly
4048 // parsed, it will never advance the preparse data beyond that
4049 // function and all further laziness will fail (all functions will be
4050 // parsed eagerly).
4051 is_lazily_parsed = false;
4017 } 4052 }
4018 } else { 4053 } else {
4019 // With no preparser data, we partially parse the function, without 4054 // With no preparser data, we partially parse the function, without
4020 // building an AST. This gathers the data needed to build a lazy 4055 // building an AST. This gathers the data needed to build a lazy
4021 // function. 4056 // function.
4022 SingletonLogger logger; 4057 SingletonLogger logger;
4023 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); 4058 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
4024 if (result == PreParser::kPreParseStackOverflow) { 4059 if (result == PreParser::kPreParseStackOverflow) {
4025 // Propagate stack overflow. 4060 // Propagate stack overflow.
4026 set_stack_overflow(); 4061 set_stack_overflow();
(...skipping 16 matching lines...) Expand all
4043 scope->set_end_position(logger.end()); 4078 scope->set_end_position(logger.end());
4044 Expect(Token::RBRACE, CHECK_OK); 4079 Expect(Token::RBRACE, CHECK_OK);
4045 isolate()->counters()->total_preparse_skipped()->Increment( 4080 isolate()->counters()->total_preparse_skipped()->Increment(
4046 scope->end_position() - function_block_pos); 4081 scope->end_position() - function_block_pos);
4047 materialized_literal_count = logger.literals(); 4082 materialized_literal_count = logger.literals();
4048 expected_property_count = logger.properties(); 4083 expected_property_count = logger.properties();
4049 scope_->SetLanguageMode(logger.language_mode()); 4084 scope_->SetLanguageMode(logger.language_mode());
4050 } 4085 }
4051 } 4086 }
4052 4087
4053 if (!is_lazily_compiled) { 4088 if (!is_lazily_parsed) {
4089 // Everything inside an eagerly parsed function will be parsed eagerly
4090 // (see comment above).
4054 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); 4091 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
4055 body = new(zone()) ZoneList<Statement*>(8, zone()); 4092 body = new(zone()) ZoneList<Statement*>(8, zone());
4056 if (fvar != NULL) { 4093 if (fvar != NULL) {
4057 VariableProxy* fproxy = scope_->NewUnresolved( 4094 VariableProxy* fproxy = scope_->NewUnresolved(
4058 factory(), function_name, Interface::NewConst()); 4095 factory(), function_name, Interface::NewConst());
4059 fproxy->BindTo(fvar); 4096 fproxy->BindTo(fvar);
4060 body->Add(factory()->NewExpressionStatement( 4097 body->Add(factory()->NewExpressionStatement(
4061 factory()->NewAssignment(fvar_init_op, 4098 factory()->NewAssignment(fvar_init_op,
4062 fproxy, 4099 fproxy,
4063 factory()->NewThisFunction(pos), 4100 factory()->NewThisFunction(pos),
(...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after
5365 ASSERT(info()->isolate()->has_pending_exception()); 5402 ASSERT(info()->isolate()->has_pending_exception());
5366 } else { 5403 } else {
5367 result = ParseProgram(); 5404 result = ParseProgram();
5368 } 5405 }
5369 } 5406 }
5370 info()->SetFunction(result); 5407 info()->SetFunction(result);
5371 return (result != NULL); 5408 return (result != NULL);
5372 } 5409 }
5373 5410
5374 } } // namespace v8::internal 5411 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698