Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_PREPARSER_H | 5 #ifndef V8_PREPARSER_H |
| 6 #define V8_PREPARSER_H | 6 #define V8_PREPARSER_H |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } | 632 bool IsPrototype() const { return type_ == kPrototypeIdentifier; } |
| 633 bool IsConstructor() const { return type_ == kConstructorIdentifier; } | 633 bool IsConstructor() const { return type_ == kConstructorIdentifier; } |
| 634 bool IsEvalOrArguments() const { | 634 bool IsEvalOrArguments() const { |
| 635 return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier; | 635 return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier; |
| 636 } | 636 } |
| 637 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } | 637 bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; } |
| 638 bool IsFutureStrictReserved() const { | 638 bool IsFutureStrictReserved() const { |
| 639 return type_ == kFutureStrictReservedIdentifier; | 639 return type_ == kFutureStrictReservedIdentifier; |
| 640 } | 640 } |
| 641 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } | 641 bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } |
| 642 V8_INLINE bool IsValidArrowParam() const { | |
| 643 // A valid identifier can be an arrow function parameter | |
| 644 // except for eval, arguments, yield, and reserved keywords. | |
| 645 return !(IsEval() || IsArguments() || IsYield() || | |
| 646 IsFutureStrictReserved()); | |
| 647 } | |
| 642 | 648 |
| 643 // Allow identifier->name()[->length()] to work. The preparser | 649 // Allow identifier->name()[->length()] to work. The preparser |
| 644 // does not need the actual positions/lengths of the identifiers. | 650 // does not need the actual positions/lengths of the identifiers. |
| 645 const PreParserIdentifier* operator->() const { return this; } | 651 const PreParserIdentifier* operator->() const { return this; } |
| 646 const PreParserIdentifier raw_name() const { return *this; } | 652 const PreParserIdentifier raw_name() const { return *this; } |
| 647 | 653 |
| 648 int position() const { return 0; } | 654 int position() const { return 0; } |
| 649 int length() const { return 0; } | 655 int length() const { return 0; } |
| 650 | 656 |
| 651 private: | 657 private: |
| 652 enum Type { | 658 enum Type { |
| 653 kUnknownIdentifier, | 659 kUnknownIdentifier, |
| 654 kFutureReservedIdentifier, | 660 kFutureReservedIdentifier, |
| 655 kFutureStrictReservedIdentifier, | 661 kFutureStrictReservedIdentifier, |
| 656 kLetIdentifier, | 662 kLetIdentifier, |
| 657 kYieldIdentifier, | 663 kYieldIdentifier, |
| 658 kEvalIdentifier, | 664 kEvalIdentifier, |
| 659 kArgumentsIdentifier, | 665 kArgumentsIdentifier, |
| 660 kPrototypeIdentifier, | 666 kPrototypeIdentifier, |
| 661 kConstructorIdentifier | 667 kConstructorIdentifier |
| 662 }; | 668 }; |
| 663 explicit PreParserIdentifier(Type type) : type_(type) {} | 669 explicit PreParserIdentifier(Type type) : type_(type) {} |
| 664 Type type_; | 670 Type type_; |
| 665 | 671 |
| 666 friend class PreParserExpression; | 672 friend class PreParserExpression; |
| 667 friend class PreParserScope; | 673 friend class PreParserScope; |
| 668 }; | 674 }; |
| 669 | 675 |
| 670 | 676 |
| 671 // Bits 0 and 1 are used to identify the type of expression: | |
| 672 // If bit 0 is set, it's an identifier. | |
| 673 // if bit 1 is set, it's a string literal. | |
| 674 // If neither is set, it's no particular type, and both set isn't | |
| 675 // use yet. | |
| 676 class PreParserExpression { | 677 class PreParserExpression { |
| 677 public: | 678 public: |
| 678 static PreParserExpression Default() { | 679 static PreParserExpression Default() { |
| 679 return PreParserExpression(kUnknownExpression); | 680 return PreParserExpression(TypeField::encode(kExpression)); |
| 680 } | 681 } |
| 681 | 682 |
| 682 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | 683 static PreParserExpression FromIdentifier(PreParserIdentifier id) { |
| 683 return PreParserExpression(kTypeIdentifier | | 684 return PreParserExpression(TypeField::encode(kIdentifierExpression) | |
| 684 (id.type_ << kIdentifierShift)); | 685 IdentifierTypeField::encode(id.type_)); |
| 685 } | 686 } |
| 686 | 687 |
| 687 static PreParserExpression BinaryOperation(PreParserExpression left, | 688 static PreParserExpression BinaryOperation(PreParserExpression left, |
| 688 Token::Value op, | 689 Token::Value op, |
| 689 PreParserExpression right) { | 690 PreParserExpression right) { |
| 690 int code = ((op == Token::COMMA) && !left.is_parenthesized() && | 691 bool valid_arrow_param_list = |
| 691 !right.is_parenthesized()) | 692 op == Token::COMMA && !left.is_parenthesized() && |
| 692 ? left.ArrowParamListBit() & right.ArrowParamListBit() | 693 !right.is_parenthesized() && left.IsValidArrowParams() && |
| 693 : 0; | 694 right.IsValidArrowParams(); |
| 694 return PreParserExpression(kTypeBinaryOperation | code); | 695 return PreParserExpression( |
| 696 TypeField::encode(kBinaryOperationExpression) | | |
| 697 IsValidArrowParamListField::encode(valid_arrow_param_list)); | |
| 695 } | 698 } |
| 696 | 699 |
| 697 static PreParserExpression EmptyArrowParamList() { | 700 static PreParserExpression EmptyArrowParamList() { |
| 698 // Any expression for which IsValidArrowParamList() returns true | 701 // Any expression for which IsValidArrowParamList() returns true |
| 699 // will work here. | 702 // will work here. |
| 700 return FromIdentifier(PreParserIdentifier::Default()); | 703 return FromIdentifier(PreParserIdentifier::Default()); |
| 701 } | 704 } |
| 702 | 705 |
| 703 static PreParserExpression StringLiteral() { | 706 static PreParserExpression StringLiteral() { |
| 704 return PreParserExpression(kUnknownStringLiteral); | 707 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | |
| 708 IsUseStrictField::encode(false)); | |
| 705 } | 709 } |
| 706 | 710 |
| 707 static PreParserExpression UseStrictStringLiteral() { | 711 static PreParserExpression UseStrictStringLiteral() { |
| 708 return PreParserExpression(kUseStrictString); | 712 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | |
| 713 IsUseStrictField::encode(true)); | |
| 709 } | 714 } |
| 710 | 715 |
| 711 static PreParserExpression This() { | 716 static PreParserExpression This() { |
| 712 return PreParserExpression(kThisExpression); | 717 return PreParserExpression(TypeField::encode(kExpression) | |
| 718 ExpressionTypeField::encode(kThisExpression)); | |
| 713 } | 719 } |
| 714 | 720 |
| 715 static PreParserExpression Super() { | 721 static PreParserExpression Super() { |
| 716 return PreParserExpression(kSuperExpression); | 722 return PreParserExpression(TypeField::encode(kExpression) | |
| 723 ExpressionTypeField::encode(kSuperExpression)); | |
| 717 } | 724 } |
| 718 | 725 |
| 719 static PreParserExpression ThisProperty() { | 726 static PreParserExpression ThisProperty() { |
| 720 return PreParserExpression(kThisPropertyExpression); | 727 return PreParserExpression( |
| 728 TypeField::encode(kExpression) | | |
| 729 ExpressionTypeField::encode(kThisPropertyExpression)); | |
| 721 } | 730 } |
| 722 | 731 |
| 723 static PreParserExpression Property() { | 732 static PreParserExpression Property() { |
| 724 return PreParserExpression(kPropertyExpression); | 733 return PreParserExpression( |
| 734 TypeField::encode(kExpression) | | |
| 735 ExpressionTypeField::encode(kPropertyExpression)); | |
| 725 } | 736 } |
| 726 | 737 |
| 727 static PreParserExpression Call() { | 738 static PreParserExpression Call() { |
| 728 return PreParserExpression(kCallExpression); | 739 return PreParserExpression(TypeField::encode(kExpression) | |
| 740 ExpressionTypeField::encode(kCallExpression)); | |
| 729 } | 741 } |
| 730 | 742 |
| 731 bool IsIdentifier() const { return (code_ & kTypeMask) == kTypeIdentifier; } | 743 bool IsIdentifier() const { |
| 744 return TypeField::decode(code_) == kIdentifierExpression; | |
| 745 } | |
| 732 | 746 |
| 733 PreParserIdentifier AsIdentifier() const { | 747 PreParserIdentifier AsIdentifier() const { |
| 734 DCHECK(IsIdentifier()); | 748 DCHECK(IsIdentifier()); |
| 735 return PreParserIdentifier( | 749 return PreParserIdentifier(IdentifierTypeField::decode(code_)); |
| 736 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); | |
| 737 } | 750 } |
| 738 | 751 |
| 739 bool IsStringLiteral() const { | 752 bool IsStringLiteral() const { |
| 740 return (code_ & kTypeMask) == kTypeStringLiteral; | 753 return TypeField::decode(code_) == kStringLiteralExpression; |
| 741 } | 754 } |
| 742 | 755 |
| 743 bool IsUseStrictLiteral() const { | 756 bool IsUseStrictLiteral() const { |
| 744 return (code_ & kUseStrictString) == kUseStrictString; | 757 return TypeField::decode(code_) == kStringLiteralExpression && |
| 758 IsUseStrictField::decode(code_); | |
| 745 } | 759 } |
| 746 | 760 |
| 747 bool IsThis() const { return (code_ & kThisExpression) == kThisExpression; } | 761 bool IsThis() const { |
| 762 return TypeField::decode(code_) == kExpression && | |
| 763 ExpressionTypeField::decode(code_) == kThisExpression; | |
| 764 } | |
| 748 | 765 |
| 749 bool IsThisProperty() const { | 766 bool IsThisProperty() const { |
| 750 return (code_ & kThisPropertyExpression) == kThisPropertyExpression; | 767 return TypeField::decode(code_) == kExpression && |
| 768 ExpressionTypeField::decode(code_) == kThisPropertyExpression; | |
| 751 } | 769 } |
| 752 | 770 |
| 753 bool IsProperty() const { | 771 bool IsProperty() const { |
| 754 return (code_ & kPropertyExpression) == kPropertyExpression || | 772 return TypeField::decode(code_) == kExpression && |
| 755 (code_ & kThisPropertyExpression) == kThisPropertyExpression; | 773 (ExpressionTypeField::decode(code_) == kPropertyExpression || |
| 774 ExpressionTypeField::decode(code_) == kThisPropertyExpression); | |
| 756 } | 775 } |
| 757 | 776 |
| 758 bool IsCall() const { return (code_ & kCallExpression) == kCallExpression; } | 777 bool IsCall() const { |
| 778 return TypeField::decode(code_) == kExpression && | |
| 779 ExpressionTypeField::decode(code_) == kCallExpression; | |
| 780 } | |
| 759 | 781 |
| 760 bool IsValidReferenceExpression() const { | 782 bool IsValidReferenceExpression() const { |
| 761 return IsIdentifier() || IsProperty(); | 783 return IsIdentifier() || IsProperty(); |
| 762 } | 784 } |
| 763 | 785 |
| 764 bool IsValidArrowParamList() const { | 786 bool IsValidArrowParamList() const { |
| 765 return (ArrowParamListBit() & kBinaryOperationArrowParamList) != 0 && | 787 return IsValidArrowParams() && |
| 766 (code_ & kMultiParenthesizedExpression) == 0; | 788 ParenthesizationField::decode(code_) != |
| 789 kMultiParenthesizedExpression; | |
| 767 } | 790 } |
| 768 | 791 |
| 769 // At the moment PreParser doesn't track these expression types. | 792 // At the moment PreParser doesn't track these expression types. |
| 770 bool IsFunctionLiteral() const { return false; } | 793 bool IsFunctionLiteral() const { return false; } |
| 771 bool IsCallNew() const { return false; } | 794 bool IsCallNew() const { return false; } |
| 772 | 795 |
| 773 PreParserExpression AsFunctionLiteral() { return *this; } | 796 PreParserExpression AsFunctionLiteral() { return *this; } |
| 774 | 797 |
| 775 bool IsBinaryOperation() const { | 798 bool IsBinaryOperation() const { |
| 776 return (code_ & kTypeMask) == kTypeBinaryOperation; | 799 return TypeField::decode(code_) == kBinaryOperationExpression; |
| 777 } | 800 } |
| 778 | 801 |
| 779 bool is_parenthesized() const { | 802 bool is_parenthesized() const { |
| 780 return (code_ & kParenthesizedExpression) != 0; | 803 return ParenthesizationField::decode(code_) != kNotParenthesized; |
| 781 } | 804 } |
| 782 | 805 |
| 783 void increase_parenthesization_level() { | 806 void increase_parenthesization_level() { |
| 784 code_ |= is_parenthesized() ? kMultiParenthesizedExpression | 807 code_ = ParenthesizationField::update( |
| 785 : kParenthesizedExpression; | 808 code_, is_parenthesized() ? kMultiParenthesizedExpression |
| 809 : kParanthesizedExpression); | |
| 786 } | 810 } |
| 787 | 811 |
| 788 // Dummy implementation for making expression->somefunc() work in both Parser | 812 // Dummy implementation for making expression->somefunc() work in both Parser |
| 789 // and PreParser. | 813 // and PreParser. |
| 790 PreParserExpression* operator->() { return this; } | 814 PreParserExpression* operator->() { return this; } |
| 791 | 815 |
| 792 // More dummy implementations of things PreParser doesn't need to track: | 816 // More dummy implementations of things PreParser doesn't need to track: |
| 793 void set_index(int index) {} // For YieldExpressions | 817 void set_index(int index) {} // For YieldExpressions |
| 794 void set_parenthesized() {} | 818 void set_parenthesized() {} |
| 795 | 819 |
| 796 int position() const { return RelocInfo::kNoPosition; } | 820 int position() const { return RelocInfo::kNoPosition; } |
| 797 void set_function_token_position(int position) {} | 821 void set_function_token_position(int position) {} |
| 798 void set_ast_properties(int* ast_properties) {} | 822 void set_ast_properties(int* ast_properties) {} |
| 799 void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {} | 823 void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {} |
| 800 | 824 |
| 801 bool operator==(const PreParserExpression& other) const { | 825 private: |
| 802 return code_ == other.code_; | 826 enum Type { |
|
marja
2015/03/10 08:45:40
Type and ExpressionType both??? What's up with tha
| |
| 803 } | 827 kExpression, |
| 804 bool operator!=(const PreParserExpression& other) const { | 828 kIdentifierExpression, |
| 805 return code_ != other.code_; | 829 kStringLiteralExpression, |
| 830 kBinaryOperationExpression | |
| 831 }; | |
| 832 | |
| 833 enum Parenthesization { | |
| 834 kNotParenthesized, | |
| 835 kParanthesizedExpression, | |
| 836 kMultiParenthesizedExpression | |
| 837 }; | |
| 838 | |
| 839 enum ExpressionType { | |
| 840 kThisExpression, | |
| 841 kThisPropertyExpression, | |
| 842 kPropertyExpression, | |
| 843 kCallExpression, | |
| 844 kSuperExpression | |
| 845 }; | |
| 846 | |
| 847 explicit PreParserExpression(uint32_t expression_code) | |
| 848 : code_(expression_code) {} | |
| 849 | |
| 850 V8_INLINE bool IsValidArrowParams() const { | |
| 851 return IsBinaryOperation() | |
| 852 ? IsValidArrowParamListField::decode(code_) | |
| 853 : (IsIdentifier() && AsIdentifier().IsValidArrowParam()); | |
| 806 } | 854 } |
| 807 | 855 |
| 808 private: | 856 // The first four bits are for the Type and Parenthesization. |
| 809 // Least significant 2 bits are used as expression type. The third least | 857 typedef BitField<Type, 0, 2> TypeField; |
| 810 // significant bit tracks whether an expression is parenthesized. If the | 858 typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField; |
| 811 // expression is an identifier or a string literal, the other bits | |
| 812 // describe the type/ (see PreParserIdentifier::Type and string literal | |
| 813 // constants below). For binary operations, the other bits are flags | |
| 814 // which further describe the contents of the expression. | |
| 815 enum { | |
| 816 kUnknownExpression = 0, | |
| 817 kTypeMask = 1 | 2, | |
| 818 kParenthesizedExpression = (1 << 2), | |
| 819 kMultiParenthesizedExpression = (1 << 3), | |
| 820 | 859 |
| 821 // Identifiers | 860 // The rest of the bits are interpreted depending on the value |
| 822 kTypeIdentifier = 1, // Used to detect labels. | 861 // of the Type field, so they can share the storage. |
| 823 kIdentifierShift = 5, | 862 typedef BitField<ExpressionType, ParenthesizationField::kNext, 3> |
| 824 kTypeStringLiteral = 2, // Used to detect directive prologue. | 863 ExpressionTypeField; |
| 825 kUnknownStringLiteral = kTypeStringLiteral, | 864 typedef BitField<bool, ParenthesizationField::kNext, 1> IsUseStrictField; |
| 826 kUseStrictString = kTypeStringLiteral | 32, | 865 typedef BitField<bool, ParenthesizationField::kNext, 1> |
| 827 kStringLiteralMask = kUseStrictString, | 866 IsValidArrowParamListField; |
| 867 typedef BitField<PreParserIdentifier::Type, ParenthesizationField::kNext, 10> | |
| 868 IdentifierTypeField; | |
| 828 | 869 |
| 829 // Binary operations. Those are needed to detect certain keywords and | 870 uint32_t code_; |
| 830 // duplicated identifier in parameter lists for arrow functions, because | |
| 831 // they are initially parsed as comma-separated expressions. | |
| 832 kTypeBinaryOperation = 3, | |
| 833 kBinaryOperationArrowParamList = (1 << 4), | |
| 834 | |
| 835 // Below here applies if neither identifier nor string literal. Reserve the | |
| 836 // 2 least significant bits for flags. | |
| 837 kThisExpression = (1 << 4), | |
| 838 kThisPropertyExpression = (2 << 4), | |
| 839 kPropertyExpression = (3 << 4), | |
| 840 kCallExpression = (4 << 4), | |
| 841 kSuperExpression = (5 << 4) | |
| 842 }; | |
| 843 | |
| 844 explicit PreParserExpression(int expression_code) : code_(expression_code) {} | |
| 845 | |
| 846 V8_INLINE int ArrowParamListBit() const { | |
| 847 if (IsBinaryOperation()) return code_ & kBinaryOperationArrowParamList; | |
| 848 if (IsIdentifier()) { | |
| 849 const PreParserIdentifier ident = AsIdentifier(); | |
| 850 // A valid identifier can be an arrow function parameter list | |
| 851 // except for eval, arguments, yield, and reserved keywords. | |
| 852 if (ident.IsEval() || ident.IsArguments() || ident.IsYield() || | |
| 853 ident.IsFutureStrictReserved()) | |
| 854 return 0; | |
| 855 return kBinaryOperationArrowParamList; | |
| 856 } | |
| 857 return 0; | |
| 858 } | |
| 859 | |
| 860 int code_; | |
| 861 }; | 871 }; |
| 862 | 872 |
| 863 | 873 |
| 864 // PreParserExpressionList doesn't actually store the expressions because | 874 // PreParserExpressionList doesn't actually store the expressions because |
| 865 // PreParser doesn't need to. | 875 // PreParser doesn't need to. |
| 866 class PreParserExpressionList { | 876 class PreParserExpressionList { |
| 867 public: | 877 public: |
| 868 // These functions make list->Add(some_expression) work (and do nothing). | 878 // These functions make list->Add(some_expression) work (and do nothing). |
| 869 PreParserExpressionList() : length_(0) {} | 879 PreParserExpressionList() : length_(0) {} |
| 870 PreParserExpressionList* operator->() { return this; } | 880 PreParserExpressionList* operator->() { return this; } |
| (...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2835 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 2845 DCHECK(IsAccessorAccessorConflict(old_type, type)); |
| 2836 // Both accessors of the same type. | 2846 // Both accessors of the same type. |
| 2837 parser()->ReportMessage("accessor_get_set"); | 2847 parser()->ReportMessage("accessor_get_set"); |
| 2838 } | 2848 } |
| 2839 *ok = false; | 2849 *ok = false; |
| 2840 } | 2850 } |
| 2841 } | 2851 } |
| 2842 } } // v8::internal | 2852 } } // v8::internal |
| 2843 | 2853 |
| 2844 #endif // V8_PREPARSER_H | 2854 #endif // V8_PREPARSER_H |
| OLD | NEW |