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 15 matching lines...) Expand all Loading... |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "api.h" | 30 #include "api.h" |
31 #include "ast.h" | 31 #include "ast.h" |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "char-predicates-inl.h" | 33 #include "char-predicates-inl.h" |
34 #include "codegen.h" | 34 #include "codegen.h" |
35 #include "compiler.h" | 35 #include "compiler.h" |
36 #include "func-name-inferrer.h" | |
37 #include "messages.h" | 36 #include "messages.h" |
38 #include "parser.h" | 37 #include "parser.h" |
39 #include "platform.h" | 38 #include "platform.h" |
40 #include "preparser.h" | 39 #include "preparser.h" |
41 #include "runtime.h" | 40 #include "runtime.h" |
42 #include "scanner-character-streams.h" | 41 #include "scanner-character-streams.h" |
43 #include "scopeinfo.h" | 42 #include "scopeinfo.h" |
44 #include "string-stream.h" | 43 #include "string-stream.h" |
45 | 44 |
46 namespace v8 { | 45 namespace v8 { |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 } | 512 } |
514 | 513 |
515 | 514 |
516 Expression* ParserTraits::ThisExpression( | 515 Expression* ParserTraits::ThisExpression( |
517 Scope* scope, | 516 Scope* scope, |
518 AstNodeFactory<AstConstructionVisitor>* factory) { | 517 AstNodeFactory<AstConstructionVisitor>* factory) { |
519 return factory->NewVariableProxy(scope->receiver()); | 518 return factory->NewVariableProxy(scope->receiver()); |
520 } | 519 } |
521 | 520 |
522 | 521 |
523 Expression* ParserTraits::ExpressionFromLiteral( | 522 Literal* ParserTraits::ExpressionFromLiteral( |
524 Token::Value token, int pos, | 523 Token::Value token, int pos, |
525 Scanner* scanner, | 524 Scanner* scanner, |
526 AstNodeFactory<AstConstructionVisitor>* factory) { | 525 AstNodeFactory<AstConstructionVisitor>* factory) { |
527 Factory* isolate_factory = parser_->isolate()->factory(); | 526 Factory* isolate_factory = parser_->isolate()->factory(); |
528 switch (token) { | 527 switch (token) { |
529 case Token::NULL_LITERAL: | 528 case Token::NULL_LITERAL: |
530 return factory->NewLiteral(isolate_factory->null_value(), pos); | 529 return factory->NewLiteral(isolate_factory->null_value(), pos); |
531 case Token::TRUE_LITERAL: | 530 case Token::TRUE_LITERAL: |
532 return factory->NewLiteral(isolate_factory->true_value(), pos); | 531 return factory->NewLiteral(isolate_factory->true_value(), pos); |
533 case Token::FALSE_LITERAL: | 532 case Token::FALSE_LITERAL: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 } | 569 } |
571 | 570 |
572 | 571 |
573 Literal* ParserTraits::GetLiteralTheHole( | 572 Literal* ParserTraits::GetLiteralTheHole( |
574 int position, AstNodeFactory<AstConstructionVisitor>* factory) { | 573 int position, AstNodeFactory<AstConstructionVisitor>* factory) { |
575 return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(), | 574 return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(), |
576 RelocInfo::kNoPosition); | 575 RelocInfo::kNoPosition); |
577 } | 576 } |
578 | 577 |
579 | 578 |
580 Expression* ParserTraits::ParseObjectLiteral(bool* ok) { | |
581 return parser_->ParseObjectLiteral(ok); | |
582 } | |
583 | |
584 | |
585 Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) { | 579 Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
586 return parser_->ParseAssignmentExpression(accept_IN, ok); | 580 return parser_->ParseAssignmentExpression(accept_IN, ok); |
587 } | 581 } |
588 | 582 |
589 | 583 |
590 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { | 584 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { |
591 return parser_->ParseV8Intrinsic(ok); | 585 return parser_->ParseV8Intrinsic(ok); |
592 } | 586 } |
593 | 587 |
594 | 588 |
| 589 FunctionLiteral* ParserTraits::ParseFunctionLiteral( |
| 590 Handle<String> name, |
| 591 Scanner::Location function_name_location, |
| 592 bool name_is_strict_reserved, |
| 593 bool is_generator, |
| 594 int function_token_position, |
| 595 FunctionLiteral::FunctionType type, |
| 596 bool* ok) { |
| 597 return parser_->ParseFunctionLiteral(name, function_name_location, |
| 598 name_is_strict_reserved, is_generator, |
| 599 function_token_position, type, ok); |
| 600 } |
| 601 |
| 602 |
595 Parser::Parser(CompilationInfo* info) | 603 Parser::Parser(CompilationInfo* info) |
596 : ParserBase<ParserTraits>(&scanner_, | 604 : ParserBase<ParserTraits>(&scanner_, |
597 info->isolate()->stack_guard()->real_climit(), | 605 info->isolate()->stack_guard()->real_climit(), |
598 info->extension(), | 606 info->extension(), |
599 info->zone(), | 607 info->zone(), |
600 this), | 608 this), |
601 isolate_(info->isolate()), | 609 isolate_(info->isolate()), |
602 symbol_cache_(0, info->zone()), | 610 symbol_cache_(0, info->zone()), |
603 script_(info->script()), | 611 script_(info->script()), |
604 scanner_(isolate_->unicode_cache()), | 612 scanner_(isolate_->unicode_cache()), |
605 reusable_preparser_(NULL), | 613 reusable_preparser_(NULL), |
606 original_scope_(NULL), | 614 original_scope_(NULL), |
607 target_stack_(NULL), | 615 target_stack_(NULL), |
608 pre_parse_data_(NULL), | 616 pre_parse_data_(NULL), |
609 fni_(NULL), | |
610 info_(info) { | 617 info_(info) { |
611 ASSERT(!script_.is_null()); | 618 ASSERT(!script_.is_null()); |
612 isolate_->set_ast_node_id(0); | 619 isolate_->set_ast_node_id(0); |
613 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); | 620 set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping); |
614 set_allow_modules(!info->is_native() && FLAG_harmony_modules); | 621 set_allow_modules(!info->is_native() && FLAG_harmony_modules); |
615 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); | 622 set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native()); |
616 set_allow_lazy(false); // Must be explicitly enabled. | 623 set_allow_lazy(false); // Must be explicitly enabled. |
617 set_allow_generators(FLAG_harmony_generators); | 624 set_allow_generators(FLAG_harmony_generators); |
618 set_allow_for_of(FLAG_harmony_iteration); | 625 set_allow_for_of(FLAG_harmony_iteration); |
619 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); | 626 set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); |
(...skipping 2867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3487 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); | 3494 Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot)); |
3488 return static_cast<LiteralType>(literal_type->value()); | 3495 return static_cast<LiteralType>(literal_type->value()); |
3489 } | 3496 } |
3490 | 3497 |
3491 | 3498 |
3492 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { | 3499 Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) { |
3493 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); | 3500 return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot))); |
3494 } | 3501 } |
3495 | 3502 |
3496 | 3503 |
3497 Expression* Parser::ParseObjectLiteral(bool* ok) { | |
3498 // ObjectLiteral :: | |
3499 // '{' (( | |
3500 // ((IdentifierName | String | Number) ':' AssignmentExpression) | | |
3501 // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral) | |
3502 // ) ',')* '}' | |
3503 // (Except that trailing comma is not required and not allowed.) | |
3504 | |
3505 int pos = peek_position(); | |
3506 ZoneList<ObjectLiteral::Property*>* properties = | |
3507 new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone()); | |
3508 int number_of_boilerplate_properties = 0; | |
3509 bool has_function = false; | |
3510 | |
3511 ObjectLiteralChecker checker(this, strict_mode()); | |
3512 | |
3513 Expect(Token::LBRACE, CHECK_OK); | |
3514 | |
3515 while (peek() != Token::RBRACE) { | |
3516 if (fni_ != NULL) fni_->Enter(); | |
3517 | |
3518 Literal* key = NULL; | |
3519 Token::Value next = peek(); | |
3520 int next_pos = peek_position(); | |
3521 | |
3522 switch (next) { | |
3523 case Token::FUTURE_RESERVED_WORD: | |
3524 case Token::FUTURE_STRICT_RESERVED_WORD: | |
3525 case Token::IDENTIFIER: { | |
3526 bool is_getter = false; | |
3527 bool is_setter = false; | |
3528 Handle<String> id = | |
3529 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | |
3530 if (fni_ != NULL) fni_->PushLiteralName(id); | |
3531 | |
3532 if ((is_getter || is_setter) && peek() != Token::COLON) { | |
3533 // Special handling of getter and setter syntax: | |
3534 // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } | |
3535 // We have already read the "get" or "set" keyword. | |
3536 Token::Value next = Next(); | |
3537 if (next != i::Token::IDENTIFIER && | |
3538 next != i::Token::FUTURE_RESERVED_WORD && | |
3539 next != i::Token::FUTURE_STRICT_RESERVED_WORD && | |
3540 next != i::Token::NUMBER && | |
3541 next != i::Token::STRING && | |
3542 !Token::IsKeyword(next)) { | |
3543 ReportUnexpectedToken(next); | |
3544 *ok = false; | |
3545 return NULL; | |
3546 } | |
3547 // Validate the property. | |
3548 PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; | |
3549 checker.CheckProperty(next, type, CHECK_OK); | |
3550 Handle<String> name = GetSymbol(); | |
3551 FunctionLiteral* value = | |
3552 ParseFunctionLiteral(name, | |
3553 scanner()->location(), | |
3554 false, // reserved words are allowed here | |
3555 false, // not a generator | |
3556 RelocInfo::kNoPosition, | |
3557 FunctionLiteral::ANONYMOUS_EXPRESSION, | |
3558 CHECK_OK); | |
3559 // Allow any number of parameters for compatibilty with JSC. | |
3560 // Specification only allows zero parameters for get and one for set. | |
3561 ObjectLiteral::Property* property = | |
3562 factory()->NewObjectLiteralProperty(is_getter, value, next_pos); | |
3563 if (ObjectLiteral::IsBoilerplateProperty(property)) { | |
3564 number_of_boilerplate_properties++; | |
3565 } | |
3566 properties->Add(property, zone()); | |
3567 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | |
3568 | |
3569 if (fni_ != NULL) { | |
3570 fni_->Infer(); | |
3571 fni_->Leave(); | |
3572 } | |
3573 continue; // restart the while | |
3574 } | |
3575 // Failed to parse as get/set property, so it's just a normal property | |
3576 // (which might be called "get" or "set" or something else). | |
3577 key = factory()->NewLiteral(id, next_pos); | |
3578 break; | |
3579 } | |
3580 case Token::STRING: { | |
3581 Consume(Token::STRING); | |
3582 Handle<String> string = GetSymbol(); | |
3583 if (fni_ != NULL) fni_->PushLiteralName(string); | |
3584 uint32_t index; | |
3585 if (!string.is_null() && string->AsArrayIndex(&index)) { | |
3586 key = factory()->NewNumberLiteral(index, next_pos); | |
3587 break; | |
3588 } | |
3589 key = factory()->NewLiteral(string, next_pos); | |
3590 break; | |
3591 } | |
3592 case Token::NUMBER: { | |
3593 Consume(Token::NUMBER); | |
3594 ASSERT(scanner()->is_literal_ascii()); | |
3595 double value = StringToDouble(isolate()->unicode_cache(), | |
3596 scanner()->literal_ascii_string(), | |
3597 ALLOW_HEX | ALLOW_OCTAL | | |
3598 ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY); | |
3599 key = factory()->NewNumberLiteral(value, next_pos); | |
3600 break; | |
3601 } | |
3602 default: | |
3603 if (Token::IsKeyword(next)) { | |
3604 Consume(next); | |
3605 Handle<String> string = GetSymbol(); | |
3606 key = factory()->NewLiteral(string, next_pos); | |
3607 } else { | |
3608 Token::Value next = Next(); | |
3609 ReportUnexpectedToken(next); | |
3610 *ok = false; | |
3611 return NULL; | |
3612 } | |
3613 } | |
3614 | |
3615 // Validate the property | |
3616 checker.CheckProperty(next, kValueProperty, CHECK_OK); | |
3617 | |
3618 Expect(Token::COLON, CHECK_OK); | |
3619 Expression* value = ParseAssignmentExpression(true, CHECK_OK); | |
3620 | |
3621 ObjectLiteral::Property* property = | |
3622 factory()->NewObjectLiteralProperty(key, value); | |
3623 | |
3624 // Mark top-level object literals that contain function literals and | |
3625 // pretenure the literal so it can be added as a constant function | |
3626 // property. | |
3627 if (scope_->DeclarationScope()->is_global_scope() && | |
3628 value->AsFunctionLiteral() != NULL) { | |
3629 has_function = true; | |
3630 value->AsFunctionLiteral()->set_pretenure(); | |
3631 } | |
3632 | |
3633 // Count CONSTANT or COMPUTED properties to maintain the enumeration order. | |
3634 if (ObjectLiteral::IsBoilerplateProperty(property)) { | |
3635 number_of_boilerplate_properties++; | |
3636 } | |
3637 properties->Add(property, zone()); | |
3638 | |
3639 // TODO(1240767): Consider allowing trailing comma. | |
3640 if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK); | |
3641 | |
3642 if (fni_ != NULL) { | |
3643 fni_->Infer(); | |
3644 fni_->Leave(); | |
3645 } | |
3646 } | |
3647 Expect(Token::RBRACE, CHECK_OK); | |
3648 | |
3649 // Computation of literal_index must happen before pre parse bailout. | |
3650 int literal_index = function_state_->NextMaterializedLiteralIndex(); | |
3651 | |
3652 return factory()->NewObjectLiteral(properties, | |
3653 literal_index, | |
3654 number_of_boilerplate_properties, | |
3655 has_function, | |
3656 pos); | |
3657 } | |
3658 | |
3659 | |
3660 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { | 3504 ZoneList<Expression*>* Parser::ParseArguments(bool* ok) { |
3661 // Arguments :: | 3505 // Arguments :: |
3662 // '(' (AssignmentExpression)*[','] ')' | 3506 // '(' (AssignmentExpression)*[','] ')' |
3663 | 3507 |
3664 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone()); | 3508 ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone()); |
3665 Expect(Token::LPAREN, CHECK_OK); | 3509 Expect(Token::LPAREN, CHECK_OK); |
3666 bool done = (peek() == Token::RPAREN); | 3510 bool done = (peek() == Token::RPAREN); |
3667 while (!done) { | 3511 while (!done) { |
3668 Expression* argument = ParseAssignmentExpression(true, CHECK_OK); | 3512 Expression* argument = ParseAssignmentExpression(true, CHECK_OK); |
3669 result->Add(argument, zone()); | 3513 result->Add(argument, zone()); |
(...skipping 1687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5357 ASSERT(info()->isolate()->has_pending_exception()); | 5201 ASSERT(info()->isolate()->has_pending_exception()); |
5358 } else { | 5202 } else { |
5359 result = ParseProgram(); | 5203 result = ParseProgram(); |
5360 } | 5204 } |
5361 } | 5205 } |
5362 info()->SetFunction(result); | 5206 info()->SetFunction(result); |
5363 return (result != NULL); | 5207 return (result != NULL); |
5364 } | 5208 } |
5365 | 5209 |
5366 } } // namespace v8::internal | 5210 } } // namespace v8::internal |
OLD | NEW |