| 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 |