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 |