 Chromium Code Reviews
 Chromium Code Reviews Issue 422363002:
  Clean up manual bit field usage in PreParserExpression  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 422363002:
  Clean up manual bit field usage in PreParserExpression  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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/func-name-inferrer.h" | 10 #include "src/func-name-inferrer.h" | 
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 kArgumentsIdentifier | 638 kArgumentsIdentifier | 
| 639 }; | 639 }; | 
| 640 explicit PreParserIdentifier(Type type) : type_(type) {} | 640 explicit PreParserIdentifier(Type type) : type_(type) {} | 
| 641 Type type_; | 641 Type type_; | 
| 642 | 642 | 
| 643 friend class PreParserExpression; | 643 friend class PreParserExpression; | 
| 644 friend class PreParserScope; | 644 friend class PreParserScope; | 
| 645 }; | 645 }; | 
| 646 | 646 | 
| 647 | 647 | 
| 648 // Bits 0 and 1 are used to identify the type of expression: | |
| 649 // If bit 0 is set, it's an identifier. | |
| 650 // if bit 1 is set, it's a string literal. | |
| 651 // If neither is set, it's no particular type, and both set isn't | |
| 652 // use yet. | |
| 653 class PreParserExpression { | 648 class PreParserExpression { | 
| 654 public: | 649 public: | 
| 655 static PreParserExpression Default() { | 650 static PreParserExpression Default() { | 
| 656 return PreParserExpression(kUnknownExpression); | 651 return PreParserExpression(TypeField::encode(kExpression)); | 
| 657 } | 652 } | 
| 658 | 653 | 
| 659 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | 654 static PreParserExpression FromIdentifier(PreParserIdentifier id) { | 
| 660 return PreParserExpression(kTypeIdentifier | | 655 return PreParserExpression(TypeField::encode(kIdentifierExpression) | | 
| 661 (id.type_ << kIdentifierShift)); | 656 IdentifierTypeField::encode(id.type_)); | 
| 662 } | 657 } | 
| 663 | 658 | 
| 664 static PreParserExpression BinaryOperation(PreParserExpression left, | 659 static PreParserExpression BinaryOperation(PreParserExpression left, | 
| 665 Token::Value op, | 660 Token::Value op, | 
| 666 PreParserExpression right) { | 661 PreParserExpression right) { | 
| 667 int code = ((op == Token::COMMA) && !left.is_parenthesized() && | 662 bool valid_arrow_param_list = | 
| 668 !right.is_parenthesized()) | 663 op == Token::COMMA && !left.is_parenthesized() && | 
| 669 ? left.ArrowParamListBit() & right.ArrowParamListBit() | 664 !right.is_parenthesized() && left.IsValidArrowParams() && | 
| 670 : 0; | 665 right.IsValidArrowParams(); | 
| 671 return PreParserExpression(kTypeBinaryOperation | code); | 666 return PreParserExpression( | 
| 667 TypeField::encode(kBinaryOperationExpression) | | |
| 668 IsValidArrowParamListField::encode(valid_arrow_param_list)); | |
| 672 } | 669 } | 
| 673 | 670 | 
| 674 static PreParserExpression EmptyArrowParamList() { | 671 static PreParserExpression EmptyArrowParamList() { | 
| 675 // Any expression for which IsValidArrowParamList() returns true | 672 // Any expression for which IsValidArrowParamList() returns true | 
| 676 // will work here. | 673 // will work here. | 
| 677 return FromIdentifier(PreParserIdentifier::Default()); | 674 return FromIdentifier(PreParserIdentifier::Default()); | 
| 678 } | 675 } | 
| 679 | 676 | 
| 680 static PreParserExpression StringLiteral() { | 677 static PreParserExpression StringLiteral() { | 
| 681 return PreParserExpression(kUnknownStringLiteral); | 678 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | | 
| 679 IsUseStrictField::encode(false)); | |
| 682 } | 680 } | 
| 683 | 681 | 
| 684 static PreParserExpression UseStrictStringLiteral() { | 682 static PreParserExpression UseStrictStringLiteral() { | 
| 685 return PreParserExpression(kUseStrictString); | 683 return PreParserExpression(TypeField::encode(kStringLiteralExpression) | | 
| 684 IsUseStrictField::encode(true)); | |
| 686 } | 685 } | 
| 687 | 686 | 
| 688 static PreParserExpression This() { | 687 static PreParserExpression This() { | 
| 689 return PreParserExpression(kThisExpression); | 688 return PreParserExpression(TypeField::encode(kExpression) | | 
| 689 ExpressionTypeField::encode(kThisExpression)); | |
| 690 } | 690 } | 
| 691 | 691 | 
| 692 static PreParserExpression Super() { | 692 static PreParserExpression Super() { | 
| 693 return PreParserExpression(kSuperExpression); | 693 return PreParserExpression(TypeField::encode(kExpression) | | 
| 694 ExpressionTypeField::encode(kSuperExpression)); | |
| 694 } | 695 } | 
| 695 | 696 | 
| 696 static PreParserExpression ThisProperty() { | 697 static PreParserExpression ThisProperty() { | 
| 697 return PreParserExpression(kThisPropertyExpression); | 698 return PreParserExpression( | 
| 699 TypeField::encode(kExpression) | | |
| 700 ExpressionTypeField::encode(kThisPropertyExpression)); | |
| 698 } | 701 } | 
| 699 | 702 | 
| 700 static PreParserExpression Property() { | 703 static PreParserExpression Property() { | 
| 701 return PreParserExpression(kPropertyExpression); | 704 return PreParserExpression( | 
| 705 TypeField::encode(kExpression) | | |
| 706 ExpressionTypeField::encode(kPropertyExpression)); | |
| 702 } | 707 } | 
| 703 | 708 | 
| 704 static PreParserExpression Call() { | 709 static PreParserExpression Call() { | 
| 705 return PreParserExpression(kCallExpression); | 710 return PreParserExpression(TypeField::encode(kExpression) | | 
| 711 ExpressionTypeField::encode(kCallExpression)); | |
| 706 } | 712 } | 
| 707 | 713 | 
| 708 bool IsIdentifier() const { return (code_ & kTypeMask) == kTypeIdentifier; } | 714 bool IsIdentifier() const { | 
| 715 return TypeField::decode(code_) == kIdentifierExpression; | |
| 716 } | |
| 709 | 717 | 
| 710 PreParserIdentifier AsIdentifier() const { | 718 PreParserIdentifier AsIdentifier() const { | 
| 711 DCHECK(IsIdentifier()); | 719 DCHECK(IsIdentifier()); | 
| 712 return PreParserIdentifier( | 720 return PreParserIdentifier(IdentifierTypeField::decode(code_)); | 
| 713 static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); | |
| 714 } | 721 } | 
| 715 | 722 | 
| 716 bool IsStringLiteral() const { | 723 bool IsStringLiteral() const { | 
| 717 return (code_ & kTypeMask) == kTypeStringLiteral; | 724 return TypeField::decode(code_) == kStringLiteralExpression; | 
| 718 } | 725 } | 
| 719 | 726 | 
| 720 bool IsUseStrictLiteral() const { | 727 bool IsUseStrictLiteral() const { | 
| 721 return (code_ & kUseStrictString) == kUseStrictString; | 728 return TypeField::decode(code_) == kStringLiteralExpression && | 
| 729 IsUseStrictField::decode(code_); | |
| 722 } | 730 } | 
| 723 | 731 | 
| 724 bool IsThis() const { return (code_ & kThisExpression) == kThisExpression; } | 732 bool IsThis() const { | 
| 733 return TypeField::decode(code_) == kExpression && | |
| 734 ExpressionTypeField::decode(code_) == kThisExpression; | |
| 735 } | |
| 725 | 736 | 
| 726 bool IsThisProperty() const { | 737 bool IsThisProperty() const { | 
| 727 return (code_ & kThisPropertyExpression) == kThisPropertyExpression; | 738 return TypeField::decode(code_) == kExpression && | 
| 739 ExpressionTypeField::decode(code_) == kThisPropertyExpression; | |
| 728 } | 740 } | 
| 729 | 741 | 
| 730 bool IsProperty() const { | 742 bool IsProperty() const { | 
| 731 return (code_ & kPropertyExpression) == kPropertyExpression || | 743 return TypeField::decode(code_) == kExpression && | 
| 732 (code_ & kThisPropertyExpression) == kThisPropertyExpression; | 744 (ExpressionTypeField::decode(code_) == kPropertyExpression || | 
| 745 ExpressionTypeField::decode(code_) == kThisPropertyExpression); | |
| 733 } | 746 } | 
| 734 | 747 | 
| 735 bool IsCall() const { return (code_ & kCallExpression) == kCallExpression; } | 748 bool IsCall() const { | 
| 749 return TypeField::decode(code_) == kExpression && | |
| 750 ExpressionTypeField::decode(code_) == kCallExpression; | |
| 751 } | |
| 736 | 752 | 
| 737 bool IsValidReferenceExpression() const { | 753 bool IsValidReferenceExpression() const { | 
| 738 return IsIdentifier() || IsProperty(); | 754 return IsIdentifier() || IsProperty(); | 
| 739 } | 755 } | 
| 740 | 756 | 
| 741 bool IsValidArrowParamList() const { | 757 bool IsValidArrowParamList() const { | 
| 742 return (ArrowParamListBit() & kBinaryOperationArrowParamList) != 0 && | 758 return IsValidArrowParams() && | 
| 743 (code_ & kMultiParenthesizedExpression) == 0; | 759 ParenthesizationField::decode(code_) != | 
| 760 kMultiParenthesizedExpression; | |
| 744 } | 761 } | 
| 745 | 762 | 
| 746 // At the moment PreParser doesn't track these expression types. | 763 // At the moment PreParser doesn't track these expression types. | 
| 747 bool IsFunctionLiteral() const { return false; } | 764 bool IsFunctionLiteral() const { return false; } | 
| 748 bool IsCallNew() const { return false; } | 765 bool IsCallNew() const { return false; } | 
| 749 | 766 | 
| 750 PreParserExpression AsFunctionLiteral() { return *this; } | 767 PreParserExpression AsFunctionLiteral() { return *this; } | 
| 751 | 768 | 
| 752 bool IsBinaryOperation() const { | 769 bool IsBinaryOperation() const { | 
| 753 return (code_ & kTypeMask) == kTypeBinaryOperation; | 770 return TypeField::decode(code_) == kBinaryOperationExpression; | 
| 754 } | 771 } | 
| 755 | 772 | 
| 756 bool is_parenthesized() const { | 773 bool is_parenthesized() const { | 
| 757 return (code_ & kParenthesizedExpression) != 0; | 774 return ParenthesizationField::decode(code_) != kNotParenthesized; | 
| 758 } | 775 } | 
| 759 | 776 | 
| 760 void increase_parenthesization_level() { | 777 void increase_parenthesization_level() { | 
| 761 code_ |= is_parenthesized() ? kMultiParenthesizedExpression | 778 code_ = ParenthesizationField::update( | 
| 762 : kParenthesizedExpression; | 779 code_, is_parenthesized() ? kMultiParenthesizedExpression | 
| 780 : kParanthesizedExpression); | |
| 763 } | 781 } | 
| 764 | 782 | 
| 765 // Dummy implementation for making expression->somefunc() work in both Parser | 783 // Dummy implementation for making expression->somefunc() work in both Parser | 
| 766 // and PreParser. | 784 // and PreParser. | 
| 767 PreParserExpression* operator->() { return this; } | 785 PreParserExpression* operator->() { return this; } | 
| 768 | 786 | 
| 769 // More dummy implementations of things PreParser doesn't need to track: | 787 // More dummy implementations of things PreParser doesn't need to track: | 
| 770 void set_index(int index) {} // For YieldExpressions | 788 void set_index(int index) {} // For YieldExpressions | 
| 771 void set_parenthesized() {} | 789 void set_parenthesized() {} | 
| 772 | 790 | 
| 773 int position() const { return RelocInfo::kNoPosition; } | 791 int position() const { return RelocInfo::kNoPosition; } | 
| 774 void set_function_token_position(int position) {} | 792 void set_function_token_position(int position) {} | 
| 775 void set_ast_properties(int* ast_properties) {} | 793 void set_ast_properties(int* ast_properties) {} | 
| 776 void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {} | 794 void set_dont_optimize_reason(BailoutReason dont_optimize_reason) {} | 
| 777 | 795 | 
| 778 bool operator==(const PreParserExpression& other) const { | |
| 779 return code_ == other.code_; | |
| 780 } | |
| 781 bool operator!=(const PreParserExpression& other) const { | |
| 782 return code_ != other.code_; | |
| 783 } | |
| 784 | |
| 785 private: | 796 private: | 
| 786 // Least significant 2 bits are used as expression type. The third least | 797 enum Type { | 
| 787 // significant bit tracks whether an expression is parenthesized. If the | 798 kExpression, | 
| 788 // expression is an identifier or a string literal, the other bits | 799 kIdentifierExpression, | 
| 789 // describe the type/ (see PreParserIdentifier::Type and string literal | 800 kStringLiteralExpression, | 
| 790 // constants below). For binary operations, the other bits are flags | 801 kBinaryOperationExpression | 
| 791 // which further describe the contents of the expression. | |
| 792 enum { | |
| 793 kUnknownExpression = 0, | |
| 794 kTypeMask = 1 | 2, | |
| 795 kParenthesizedExpression = (1 << 2), | |
| 796 kMultiParenthesizedExpression = (1 << 3), | |
| 797 | |
| 798 // Identifiers | |
| 799 kTypeIdentifier = 1, // Used to detect labels. | |
| 800 kIdentifierShift = 5, | |
| 801 kTypeStringLiteral = 2, // Used to detect directive prologue. | |
| 802 kUnknownStringLiteral = kTypeStringLiteral, | |
| 803 kUseStrictString = kTypeStringLiteral | 32, | |
| 804 kStringLiteralMask = kUseStrictString, | |
| 805 | |
| 806 // Binary operations. Those are needed to detect certain keywords and | |
| 807 // duplicated identifier in parameter lists for arrow functions, because | |
| 808 // they are initially parsed as comma-separated expressions. | |
| 809 kTypeBinaryOperation = 3, | |
| 810 kBinaryOperationArrowParamList = (1 << 4), | |
| 811 | |
| 812 // Below here applies if neither identifier nor string literal. Reserve the | |
| 813 // 2 least significant bits for flags. | |
| 814 kThisExpression = (1 << 4), | |
| 815 kThisPropertyExpression = (2 << 4), | |
| 816 kPropertyExpression = (3 << 4), | |
| 817 kCallExpression = (4 << 4), | |
| 818 kSuperExpression = (5 << 4) | |
| 819 }; | 802 }; | 
| 820 | 803 | 
| 821 explicit PreParserExpression(int expression_code) : code_(expression_code) {} | 804 enum Parenthesization { | 
| 805 kNotParenthesized, | |
| 806 kParanthesizedExpression, | |
| 807 kMultiParenthesizedExpression | |
| 808 }; | |
| 822 | 809 | 
| 823 V8_INLINE int ArrowParamListBit() const { | 810 enum ExpressionType { | 
| 824 if (IsBinaryOperation()) return code_ & kBinaryOperationArrowParamList; | 811 kThisExpression, | 
| 812 kThisPropertyExpression, | |
| 813 kPropertyExpression, | |
| 814 kCallExpression, | |
| 815 kSuperExpression | |
| 816 }; | |
| 817 | |
| 818 explicit PreParserExpression(uint32_t expression_code) | |
| 819 : code_(expression_code) {} | |
| 820 | |
| 821 V8_INLINE bool IsValidArrowParams() const { | |
| 822 if (IsBinaryOperation()) return IsValidArrowParamListField::decode(code_); | |
| 825 if (IsIdentifier()) { | 823 if (IsIdentifier()) { | 
| 
Sven Panne
2014/09/08 10:35:52
Use a separate predicate and simplify things:
---
 
aperez
2014/09/10 14:24:03
Acknowledged.
 | |
| 826 const PreParserIdentifier ident = AsIdentifier(); | 824 const PreParserIdentifier ident = AsIdentifier(); | 
| 827 // A valid identifier can be an arrow function parameter list | 825 // A valid identifier can be an arrow function parameter list | 
| 828 // except for eval, arguments, yield, and reserved keywords. | 826 // except for eval, arguments, yield, and reserved keywords. | 
| 829 if (ident.IsEval() || ident.IsArguments() || ident.IsYield() || | 827 if (ident.IsEval() || ident.IsArguments() || ident.IsYield() || | 
| 830 ident.IsFutureStrictReserved()) | 828 ident.IsFutureStrictReserved()) | 
| 831 return 0; | 829 return false; | 
| 832 return kBinaryOperationArrowParamList; | 830 return true; | 
| 833 } | 831 } | 
| 834 return 0; | 832 return false; | 
| 835 } | 833 } | 
| 836 | 834 | 
| 837 int code_; | 835 // The first four bits are for the Type and Parenthesization. | 
| 836 typedef BitField<Type, 0, 2> TypeField; | |
| 837 typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField; | |
| 838 | |
| 839 // The rest of the bits are interpreted depending on the value | |
| 840 // of the Type field, so they can share the storage. | |
| 841 typedef BitField<ExpressionType, ParenthesizationField::kNext, 3> | |
| 842 ExpressionTypeField; | |
| 843 typedef BitField<bool, ParenthesizationField::kNext, 1> IsUseStrictField; | |
| 844 typedef BitField<bool, ParenthesizationField::kNext, 1> | |
| 845 IsValidArrowParamListField; | |
| 846 typedef BitField<PreParserIdentifier::Type, ParenthesizationField::kNext, 10> | |
| 847 IdentifierTypeField; | |
| 848 | |
| 849 uint32_t code_; | |
| 838 }; | 850 }; | 
| 839 | 851 | 
| 840 | 852 | 
| 841 // PreParserExpressionList doesn't actually store the expressions because | 853 // PreParserExpressionList doesn't actually store the expressions because | 
| 842 // PreParser doesn't need to. | 854 // PreParser doesn't need to. | 
| 843 class PreParserExpressionList { | 855 class PreParserExpressionList { | 
| 844 public: | 856 public: | 
| 845 // These functions make list->Add(some_expression) work (and do nothing). | 857 // These functions make list->Add(some_expression) work (and do nothing). | 
| 846 PreParserExpressionList() : length_(0) {} | 858 PreParserExpressionList() : length_(0) {} | 
| 847 PreParserExpressionList* operator->() { return this; } | 859 PreParserExpressionList* operator->() { return this; } | 
| (...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2661 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 2673 DCHECK(IsAccessorAccessorConflict(old_type, type)); | 
| 2662 // Both accessors of the same type. | 2674 // Both accessors of the same type. | 
| 2663 parser()->ReportMessage("accessor_get_set"); | 2675 parser()->ReportMessage("accessor_get_set"); | 
| 2664 } | 2676 } | 
| 2665 *ok = false; | 2677 *ok = false; | 
| 2666 } | 2678 } | 
| 2667 } | 2679 } | 
| 2668 } } // v8::internal | 2680 } } // v8::internal | 
| 2669 | 2681 | 
| 2670 #endif // V8_PREPARSER_H | 2682 #endif // V8_PREPARSER_H | 
| OLD | NEW |