Chromium Code Reviews| 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 3955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 is_lazily_parsed = false; |
|
Sven Panne
2014/02/19 09:51:11
Mind explosion... o_O Can we add a comment here, t
marja
2014/02/19 12:19:47
This is just an error case, where we do have prepa
| |
| 4017 } | 4039 } |
| 4018 } else { | 4040 } else { |
| 4019 // With no preparser data, we partially parse the function, without | 4041 // With no preparser data, we partially parse the function, without |
| 4020 // building an AST. This gathers the data needed to build a lazy | 4042 // building an AST. This gathers the data needed to build a lazy |
| 4021 // function. | 4043 // function. |
| 4022 SingletonLogger logger; | 4044 SingletonLogger logger; |
| 4023 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); | 4045 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger); |
| 4024 if (result == PreParser::kPreParseStackOverflow) { | 4046 if (result == PreParser::kPreParseStackOverflow) { |
| 4025 // Propagate stack overflow. | 4047 // Propagate stack overflow. |
| 4026 set_stack_overflow(); | 4048 set_stack_overflow(); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 4043 scope->set_end_position(logger.end()); | 4065 scope->set_end_position(logger.end()); |
| 4044 Expect(Token::RBRACE, CHECK_OK); | 4066 Expect(Token::RBRACE, CHECK_OK); |
| 4045 isolate()->counters()->total_preparse_skipped()->Increment( | 4067 isolate()->counters()->total_preparse_skipped()->Increment( |
| 4046 scope->end_position() - function_block_pos); | 4068 scope->end_position() - function_block_pos); |
| 4047 materialized_literal_count = logger.literals(); | 4069 materialized_literal_count = logger.literals(); |
| 4048 expected_property_count = logger.properties(); | 4070 expected_property_count = logger.properties(); |
| 4049 scope_->SetLanguageMode(logger.language_mode()); | 4071 scope_->SetLanguageMode(logger.language_mode()); |
| 4050 } | 4072 } |
| 4051 } | 4073 } |
| 4052 | 4074 |
| 4053 if (!is_lazily_compiled) { | 4075 if (!is_lazily_parsed) { |
| 4076 // Everything inside an eagerly parsed function will be parsed eagerly | |
| 4077 // (see comment above). | |
| 4054 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); | 4078 ParsingModeScope parsing_mode(this, PARSE_EAGERLY); |
| 4055 body = new(zone()) ZoneList<Statement*>(8, zone()); | 4079 body = new(zone()) ZoneList<Statement*>(8, zone()); |
| 4056 if (fvar != NULL) { | 4080 if (fvar != NULL) { |
| 4057 VariableProxy* fproxy = scope_->NewUnresolved( | 4081 VariableProxy* fproxy = scope_->NewUnresolved( |
| 4058 factory(), function_name, Interface::NewConst()); | 4082 factory(), function_name, Interface::NewConst()); |
| 4059 fproxy->BindTo(fvar); | 4083 fproxy->BindTo(fvar); |
| 4060 body->Add(factory()->NewExpressionStatement( | 4084 body->Add(factory()->NewExpressionStatement( |
| 4061 factory()->NewAssignment(fvar_init_op, | 4085 factory()->NewAssignment(fvar_init_op, |
| 4062 fproxy, | 4086 fproxy, |
| 4063 factory()->NewThisFunction(pos), | 4087 factory()->NewThisFunction(pos), |
| (...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5365 ASSERT(info()->isolate()->has_pending_exception()); | 5389 ASSERT(info()->isolate()->has_pending_exception()); |
| 5366 } else { | 5390 } else { |
| 5367 result = ParseProgram(); | 5391 result = ParseProgram(); |
| 5368 } | 5392 } |
| 5369 } | 5393 } |
| 5370 info()->SetFunction(result); | 5394 info()->SetFunction(result); |
| 5371 return (result != NULL); | 5395 return (result != NULL); |
| 5372 } | 5396 } |
| 5373 | 5397 |
| 5374 } } // namespace v8::internal | 5398 } } // namespace v8::internal |
| OLD | NEW |