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

Side by Side Diff: src/parser.cc

Issue 237243003: Refactor ParseFunctionLiteral. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: . Created 6 years, 8 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 | « src/parser.h ('k') | no next file » | 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 3240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3251 : NewScope(scope_, FUNCTION_SCOPE); 3251 : NewScope(scope_, FUNCTION_SCOPE);
3252 ZoneList<Statement*>* body = NULL; 3252 ZoneList<Statement*>* body = NULL;
3253 int materialized_literal_count = -1; 3253 int materialized_literal_count = -1;
3254 int expected_property_count = -1; 3254 int expected_property_count = -1;
3255 int handler_count = 0; 3255 int handler_count = 0;
3256 FunctionLiteral::ParameterFlag duplicate_parameters = 3256 FunctionLiteral::ParameterFlag duplicate_parameters =
3257 FunctionLiteral::kNoDuplicateParameters; 3257 FunctionLiteral::kNoDuplicateParameters;
3258 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ 3258 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
3259 ? FunctionLiteral::kIsParenthesized 3259 ? FunctionLiteral::kIsParenthesized
3260 : FunctionLiteral::kNotParenthesized; 3260 : FunctionLiteral::kNotParenthesized;
3261 FunctionLiteral::IsGeneratorFlag generator = is_generator
3262 ? FunctionLiteral::kIsGenerator
3263 : FunctionLiteral::kNotGenerator;
3264 DeferredFeedbackSlotProcessor* slot_processor; 3261 DeferredFeedbackSlotProcessor* slot_processor;
3265 AstProperties ast_properties; 3262 AstProperties ast_properties;
3266 BailoutReason dont_optimize_reason = kNoReason; 3263 BailoutReason dont_optimize_reason = kNoReason;
3267 // Parse function body. 3264 // Parse function body.
3268 { FunctionState function_state(&function_state_, &scope_, scope, zone()); 3265 { FunctionState function_state(&function_state_, &scope_, scope, zone());
3269 scope_->SetScopeName(function_name); 3266 scope_->SetScopeName(function_name);
3270 3267
3271 if (is_generator) { 3268 if (is_generator) {
3272 // For generators, allocating variables in contexts is currently a win 3269 // For generators, allocating variables in contexts is currently a win
3273 // because it minimizes the work needed to suspend and resume an 3270 // because it minimizes the work needed to suspend and resume an
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 // that it will be compiled lazily. 3379 // that it will be compiled lazily.
3383 3380
3384 // To make this additional case work, both Parser and PreParser implement a 3381 // To make this additional case work, both Parser and PreParser implement a
3385 // logic where only top-level functions will be parsed lazily. 3382 // logic where only top-level functions will be parsed lazily.
3386 bool is_lazily_parsed = (mode() == PARSE_LAZILY && 3383 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3387 scope_->AllowsLazyCompilation() && 3384 scope_->AllowsLazyCompilation() &&
3388 !parenthesized_function_); 3385 !parenthesized_function_);
3389 parenthesized_function_ = false; // The bit was set for this function only. 3386 parenthesized_function_ = false; // The bit was set for this function only.
3390 3387
3391 if (is_lazily_parsed) { 3388 if (is_lazily_parsed) {
3392 int function_block_pos = position(); 3389 SkipLazyFunctionBody(function_name, &materialized_literal_count,
3393 FunctionEntry entry; 3390 &expected_property_count, CHECK_OK);
3394 if (cached_data_mode_ == CONSUME_CACHED_DATA) { 3391 } else {
3395 // If we have cached data, we use it to skip parsing the function body. 3392 body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
3396 // The data contains the information we need to construct the lazy 3393 is_generator, CHECK_OK);
3397 // function.
3398 entry = (*cached_data())->GetFunctionEntry(function_block_pos);
3399 if (entry.is_valid()) {
3400 if (entry.end_pos() <= function_block_pos) {
3401 // End position greater than end of stream is safe, and hard
3402 // to check.
3403 ReportInvalidCachedData(function_name, CHECK_OK);
3404 }
3405 scanner()->SeekForward(entry.end_pos() - 1);
3406
3407 scope->set_end_position(entry.end_pos());
3408 Expect(Token::RBRACE, CHECK_OK);
3409 isolate()->counters()->total_preparse_skipped()->Increment(
3410 scope->end_position() - function_block_pos);
3411 materialized_literal_count = entry.literal_count();
3412 expected_property_count = entry.property_count();
3413 scope_->SetStrictMode(entry.strict_mode());
3414 } else {
3415 // This case happens when we have preparse data but it doesn't contain
3416 // an entry for the function. Fail the compilation.
3417 ReportInvalidCachedData(function_name, CHECK_OK);
3418 }
3419 } else {
3420 // With no cached data, we partially parse the function, without
3421 // building an AST. This gathers the data needed to build a lazy
3422 // function.
3423 SingletonLogger logger;
3424 PreParser::PreParseResult result = LazyParseFunctionLiteral(&logger);
3425 if (result == PreParser::kPreParseStackOverflow) {
3426 // Propagate stack overflow.
3427 set_stack_overflow();
3428 *ok = false;
3429 return NULL;
3430 }
3431 if (logger.has_error()) {
3432 const char* arg = logger.argument_opt();
3433 Vector<const char*> args;
3434 if (arg != NULL) {
3435 args = Vector<const char*>(&arg, 1);
3436 }
3437 ParserTraits::ReportMessageAt(
3438 Scanner::Location(logger.start(), logger.end()),
3439 logger.message(), args, logger.is_reference_error());
3440 *ok = false;
3441 return NULL;
3442 }
3443 scope->set_end_position(logger.end());
3444 Expect(Token::RBRACE, CHECK_OK);
3445 isolate()->counters()->total_preparse_skipped()->Increment(
3446 scope->end_position() - function_block_pos);
3447 materialized_literal_count = logger.literals();
3448 expected_property_count = logger.properties();
3449 scope_->SetStrictMode(logger.strict_mode());
3450 if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
3451 ASSERT(log_);
3452 // Position right after terminal '}'.
3453 int body_end = scanner()->location().end_pos;
3454 log_->LogFunction(function_block_pos, body_end,
3455 materialized_literal_count,
3456 expected_property_count,
3457 scope_->strict_mode());
3458 }
3459 }
3460 }
3461
3462 if (!is_lazily_parsed) {
3463 // Everything inside an eagerly parsed function will be parsed eagerly
3464 // (see comment above).
3465 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3466 body = new(zone()) ZoneList<Statement*>(8, zone());
3467 if (fvar != NULL) {
3468 VariableProxy* fproxy = scope_->NewUnresolved(
3469 factory(), function_name, Interface::NewConst());
3470 fproxy->BindTo(fvar);
3471 body->Add(factory()->NewExpressionStatement(
3472 factory()->NewAssignment(fvar_init_op,
3473 fproxy,
3474 factory()->NewThisFunction(pos),
3475 RelocInfo::kNoPosition),
3476 RelocInfo::kNoPosition), zone());
3477 }
3478
3479 // For generators, allocate and yield an iterator on function entry.
3480 if (is_generator) {
3481 ZoneList<Expression*>* arguments =
3482 new(zone()) ZoneList<Expression*>(0, zone());
3483 CallRuntime* allocation = factory()->NewCallRuntime(
3484 isolate()->factory()->empty_string(),
3485 Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
3486 arguments, pos);
3487 VariableProxy* init_proxy = factory()->NewVariableProxy(
3488 function_state_->generator_object_variable());
3489 Assignment* assignment = factory()->NewAssignment(
3490 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3491 VariableProxy* get_proxy = factory()->NewVariableProxy(
3492 function_state_->generator_object_variable());
3493 Yield* yield = factory()->NewYield(
3494 get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
3495 body->Add(factory()->NewExpressionStatement(
3496 yield, RelocInfo::kNoPosition), zone());
3497 }
3498
3499 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
3500
3501 if (is_generator) {
3502 VariableProxy* get_proxy = factory()->NewVariableProxy(
3503 function_state_->generator_object_variable());
3504 Expression *undefined = factory()->NewLiteral(
3505 isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
3506 Yield* yield = factory()->NewYield(
3507 get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
3508 body->Add(factory()->NewExpressionStatement(
3509 yield, RelocInfo::kNoPosition), zone());
3510 }
3511
3512 materialized_literal_count = function_state.materialized_literal_count(); 3394 materialized_literal_count = function_state.materialized_literal_count();
3513 expected_property_count = function_state.expected_property_count(); 3395 expected_property_count = function_state.expected_property_count();
3514 handler_count = function_state.handler_count(); 3396 handler_count = function_state.handler_count();
3515
3516 Expect(Token::RBRACE, CHECK_OK);
3517 scope->set_end_position(scanner()->location().end_pos);
3518 } 3397 }
3519 3398
3520 // Validate strict mode. We can do this only after parsing the function, 3399 // Validate strict mode. We can do this only after parsing the function,
3521 // since the function can declare itself strict. 3400 // since the function can declare itself strict.
3522 if (strict_mode() == STRICT) { 3401 if (strict_mode() == STRICT) {
3523 if (IsEvalOrArguments(function_name)) { 3402 if (IsEvalOrArguments(function_name)) {
3524 ReportMessageAt(function_name_location, "strict_eval_arguments"); 3403 ReportMessageAt(function_name_location, "strict_eval_arguments");
3525 *ok = false; 3404 *ok = false;
3526 return NULL; 3405 return NULL;
3527 } 3406 }
(...skipping 23 matching lines...) Expand all
3551 } 3430 }
3552 ast_properties = *factory()->visitor()->ast_properties(); 3431 ast_properties = *factory()->visitor()->ast_properties();
3553 slot_processor = factory()->visitor()->slot_processor(); 3432 slot_processor = factory()->visitor()->slot_processor();
3554 dont_optimize_reason = factory()->visitor()->dont_optimize_reason(); 3433 dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
3555 } 3434 }
3556 3435
3557 if (allow_harmony_scoping() && strict_mode() == STRICT) { 3436 if (allow_harmony_scoping() && strict_mode() == STRICT) {
3558 CheckConflictingVarDeclarations(scope, CHECK_OK); 3437 CheckConflictingVarDeclarations(scope, CHECK_OK);
3559 } 3438 }
3560 3439
3440 FunctionLiteral::IsGeneratorFlag generator = is_generator
3441 ? FunctionLiteral::kIsGenerator
3442 : FunctionLiteral::kNotGenerator;
3561 FunctionLiteral* function_literal = 3443 FunctionLiteral* function_literal =
3562 factory()->NewFunctionLiteral(function_name, 3444 factory()->NewFunctionLiteral(function_name,
3563 scope, 3445 scope,
3564 body, 3446 body,
3565 materialized_literal_count, 3447 materialized_literal_count,
3566 expected_property_count, 3448 expected_property_count,
3567 handler_count, 3449 handler_count,
3568 num_parameters, 3450 num_parameters,
3569 duplicate_parameters, 3451 duplicate_parameters,
3570 function_type, 3452 function_type,
3571 FunctionLiteral::kIsFunction, 3453 FunctionLiteral::kIsFunction,
3572 parenthesized, 3454 parenthesized,
3573 generator, 3455 generator,
3574 pos); 3456 pos);
3575 function_literal->set_function_token_position(function_token_pos); 3457 function_literal->set_function_token_position(function_token_pos);
3576 function_literal->set_ast_properties(&ast_properties); 3458 function_literal->set_ast_properties(&ast_properties);
3577 function_literal->set_slot_processor(slot_processor); 3459 function_literal->set_slot_processor(slot_processor);
3578 function_literal->set_dont_optimize_reason(dont_optimize_reason); 3460 function_literal->set_dont_optimize_reason(dont_optimize_reason);
3579 3461
3580 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal); 3462 if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
3581 return function_literal; 3463 return function_literal;
3582 } 3464 }
3583 3465
3584 3466
3585 PreParser::PreParseResult Parser::LazyParseFunctionLiteral( 3467 void Parser::SkipLazyFunctionBody(Handle<String> function_name,
3468 int* materialized_literal_count,
3469 int* expected_property_count,
3470 bool* ok) {
3471 int function_block_pos = position();
3472 if (cached_data_mode_ == CONSUME_CACHED_DATA) {
3473 // If we have cached data, we use it to skip parsing the function body. The
3474 // data contains the information we need to construct the lazy function.
3475 FunctionEntry entry =
3476 (*cached_data())->GetFunctionEntry(function_block_pos);
3477 if (entry.is_valid()) {
3478 if (entry.end_pos() <= function_block_pos) {
3479 // End position greater than end of stream is safe, and hard to check.
3480 ReportInvalidCachedData(function_name, ok);
3481 if (!*ok) {
3482 return;
3483 }
3484 }
3485 scanner()->SeekForward(entry.end_pos() - 1);
3486
3487 scope_->set_end_position(entry.end_pos());
3488 Expect(Token::RBRACE, ok);
3489 if (!*ok) {
3490 return;
3491 }
3492 isolate()->counters()->total_preparse_skipped()->Increment(
3493 scope_->end_position() - function_block_pos);
3494 *materialized_literal_count = entry.literal_count();
3495 *expected_property_count = entry.property_count();
3496 scope_->SetStrictMode(entry.strict_mode());
3497 } else {
3498 // This case happens when we have preparse data but it doesn't contain an
3499 // entry for the function. Fail the compilation.
3500 ReportInvalidCachedData(function_name, ok);
3501 return;
3502 }
3503 } else {
3504 // With no cached data, we partially parse the function, without building an
3505 // AST. This gathers the data needed to build a lazy function.
3506 SingletonLogger logger;
3507 PreParser::PreParseResult result =
3508 ParseLazyFunctionBodyWithPreParser(&logger);
3509 if (result == PreParser::kPreParseStackOverflow) {
3510 // Propagate stack overflow.
3511 set_stack_overflow();
3512 *ok = false;
3513 return;
3514 }
3515 if (logger.has_error()) {
3516 const char* arg = logger.argument_opt();
3517 Vector<const char*> args;
3518 if (arg != NULL) {
3519 args = Vector<const char*>(&arg, 1);
3520 }
3521 ParserTraits::ReportMessageAt(
3522 Scanner::Location(logger.start(), logger.end()),
3523 logger.message(), args, logger.is_reference_error());
3524 *ok = false;
3525 return;
3526 }
3527 scope_->set_end_position(logger.end());
3528 Expect(Token::RBRACE, ok);
3529 if (!*ok) {
3530 return;
3531 }
3532 isolate()->counters()->total_preparse_skipped()->Increment(
3533 scope_->end_position() - function_block_pos);
3534 *materialized_literal_count = logger.literals();
3535 *expected_property_count = logger.properties();
3536 scope_->SetStrictMode(logger.strict_mode());
3537 if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
3538 ASSERT(log_);
3539 // Position right after terminal '}'.
3540 int body_end = scanner()->location().end_pos;
3541 log_->LogFunction(function_block_pos, body_end,
3542 *materialized_literal_count,
3543 *expected_property_count,
3544 scope_->strict_mode());
3545 }
3546 }
3547 }
3548
3549
3550 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
3551 Handle<String> function_name, int pos, Variable* fvar,
3552 Token::Value fvar_init_op, bool is_generator, bool* ok) {
3553 // Everything inside an eagerly parsed function will be parsed eagerly
3554 // (see comment above).
3555 ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3556 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
3557 if (fvar != NULL) {
3558 VariableProxy* fproxy = scope_->NewUnresolved(
3559 factory(), function_name, Interface::NewConst());
3560 fproxy->BindTo(fvar);
3561 body->Add(factory()->NewExpressionStatement(
3562 factory()->NewAssignment(fvar_init_op,
3563 fproxy,
3564 factory()->NewThisFunction(pos),
3565 RelocInfo::kNoPosition),
3566 RelocInfo::kNoPosition), zone());
3567 }
3568
3569 // For generators, allocate and yield an iterator on function entry.
3570 if (is_generator) {
3571 ZoneList<Expression*>* arguments =
3572 new(zone()) ZoneList<Expression*>(0, zone());
3573 CallRuntime* allocation = factory()->NewCallRuntime(
3574 isolate()->factory()->empty_string(),
3575 Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
3576 arguments, pos);
3577 VariableProxy* init_proxy = factory()->NewVariableProxy(
3578 function_state_->generator_object_variable());
3579 Assignment* assignment = factory()->NewAssignment(
3580 Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3581 VariableProxy* get_proxy = factory()->NewVariableProxy(
3582 function_state_->generator_object_variable());
3583 Yield* yield = factory()->NewYield(
3584 get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
3585 body->Add(factory()->NewExpressionStatement(
3586 yield, RelocInfo::kNoPosition), zone());
3587 }
3588
3589 ParseSourceElements(body, Token::RBRACE, false, false, CHECK_OK);
3590
3591 if (is_generator) {
3592 VariableProxy* get_proxy = factory()->NewVariableProxy(
3593 function_state_->generator_object_variable());
3594 Expression *undefined = factory()->NewLiteral(
3595 isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
3596 Yield* yield = factory()->NewYield(
3597 get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
3598 body->Add(factory()->NewExpressionStatement(
3599 yield, RelocInfo::kNoPosition), zone());
3600 }
3601
3602 Expect(Token::RBRACE, CHECK_OK);
3603 scope_->set_end_position(scanner()->location().end_pos);
3604
3605 return body;
3606 }
3607
3608
3609 PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
3586 SingletonLogger* logger) { 3610 SingletonLogger* logger) {
3587 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse()); 3611 HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
3588 ASSERT_EQ(Token::LBRACE, scanner()->current_token()); 3612 ASSERT_EQ(Token::LBRACE, scanner()->current_token());
3589 3613
3590 if (reusable_preparser_ == NULL) { 3614 if (reusable_preparser_ == NULL) {
3591 intptr_t stack_limit = isolate()->stack_guard()->real_climit(); 3615 intptr_t stack_limit = isolate()->stack_guard()->real_climit();
3592 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit); 3616 reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
3593 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping()); 3617 reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3594 reusable_preparser_->set_allow_modules(allow_modules()); 3618 reusable_preparser_->set_allow_modules(allow_modules());
3595 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax()); 3619 reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
(...skipping 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after
4669 ASSERT(info()->isolate()->has_pending_exception()); 4693 ASSERT(info()->isolate()->has_pending_exception());
4670 } else { 4694 } else {
4671 result = ParseProgram(); 4695 result = ParseProgram();
4672 } 4696 }
4673 } 4697 }
4674 info()->SetFunction(result); 4698 info()->SetFunction(result);
4675 return (result != NULL); 4699 return (result != NULL);
4676 } 4700 }
4677 4701
4678 } } // namespace v8::internal 4702 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698