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