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 // 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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 // Represents the location of one element relative to the intersection of | 218 // Represents the location of one element relative to the intersection of |
| 219 // two sets. Corresponds to the four areas of a Venn diagram. | 219 // two sets. Corresponds to the four areas of a Venn diagram. |
| 220 enum ElementInSetsRelation { | 220 enum ElementInSetsRelation { |
| 221 kInsideNone = 0, | 221 kInsideNone = 0, |
| 222 kInsideFirst = 1, | 222 kInsideFirst = 1, |
| 223 kInsideSecond = 2, | 223 kInsideSecond = 2, |
| 224 kInsideBoth = 3 | 224 kInsideBoth = 3 |
| 225 }; | 225 }; |
| 226 | 226 |
| 227 | 227 |
| 228 // Represents code units in the range from from_ to to_, both ends are | |
| 229 // inclusive. | |
| 228 class CharacterRange { | 230 class CharacterRange { |
| 229 public: | 231 public: |
| 230 CharacterRange() : from_(0), to_(0) { } | 232 CharacterRange() : from_(0), to_(0) { } |
| 231 // For compatibility with the CHECK_OK macro | 233 // For compatibility with the CHECK_OK macro |
| 232 CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT | 234 CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT |
| 233 CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { } | 235 CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { } |
| 234 static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges); | 236 static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges); |
| 235 static Vector<const int> GetWordBounds(); | 237 static Vector<const int> GetWordBounds(); |
| 236 static inline CharacterRange Singleton(uc16 value) { | 238 static inline CharacterRange Singleton(uc16 value) { |
| 237 return CharacterRange(value, value); | 239 return CharacterRange(value, value); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 512 Position positions_[4]; | 514 Position positions_[4]; |
| 513 // These values are the condensate of the above array after Rationalize(). | 515 // These values are the condensate of the above array after Rationalize(). |
| 514 uint32_t mask_; | 516 uint32_t mask_; |
| 515 uint32_t value_; | 517 uint32_t value_; |
| 516 // If set to true, there is no way this quick check can match at all. | 518 // If set to true, there is no way this quick check can match at all. |
| 517 // E.g., if it requires to be at the start of the input, and isn't. | 519 // E.g., if it requires to be at the start of the input, and isn't. |
| 518 bool cannot_match_; | 520 bool cannot_match_; |
| 519 }; | 521 }; |
| 520 | 522 |
| 521 | 523 |
| 524 extern int kUninitializedRegExpNodePlaceHolder; | |
| 525 | |
| 526 | |
| 522 class RegExpNode: public ZoneObject { | 527 class RegExpNode: public ZoneObject { |
| 523 public: | 528 public: |
| 524 RegExpNode() : trace_count_(0) { | 529 RegExpNode() : replacement_(Uninitialized()), trace_count_(0) { |
| 525 bm_info_[0] = bm_info_[1] = NULL; | 530 bm_info_[0] = bm_info_[1] = NULL; |
| 526 } | 531 } |
| 527 virtual ~RegExpNode(); | 532 virtual ~RegExpNode(); |
| 528 virtual void Accept(NodeVisitor* visitor) = 0; | 533 virtual void Accept(NodeVisitor* visitor) = 0; |
| 529 // Generates a goto to this node or actually generates the code at this point. | 534 // Generates a goto to this node or actually generates the code at this point. |
| 530 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; | 535 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; |
| 531 // How many characters must this node consume at a minimum in order to | 536 // How many characters must this node consume at a minimum in order to |
| 532 // succeed. If we have found at least 'still_to_find' characters that | 537 // succeed. If we have found at least 'still_to_find' characters that |
| 533 // must be consumed there is no need to ask any following nodes whether | 538 // must be consumed there is no need to ask any following nodes whether |
| 534 // they are sure to eat any more characters. The not_at_start argument is | 539 // they are sure to eat any more characters. The not_at_start argument is |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 565 } | 570 } |
| 566 | 571 |
| 567 // Collects information on the possible code units (mod 128) that can match if | 572 // Collects information on the possible code units (mod 128) that can match if |
| 568 // we look forward. This is used for a Boyer-Moore-like string searching | 573 // we look forward. This is used for a Boyer-Moore-like string searching |
| 569 // implementation. TODO(erikcorry): This should share more code with | 574 // implementation. TODO(erikcorry): This should share more code with |
| 570 // EatsAtLeast, GetQuickCheckDetails. | 575 // EatsAtLeast, GetQuickCheckDetails. |
| 571 virtual void FillInBMInfo( | 576 virtual void FillInBMInfo( |
| 572 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | 577 int offset, BoyerMooreLookahead* bm, bool not_at_start) { |
| 573 UNREACHABLE(); | 578 UNREACHABLE(); |
| 574 } | 579 } |
| 580 | |
| 581 // If we know that the input is ASCII then there are some nodes that can | |
| 582 // never match. This method returns returns a node that can be substituted | |
|
ulan
2012/04/25 12:55:28
double "returns"
Erik Corry
2012/04/26 08:23:11
done done
| |
| 583 // for itself, or NULL if the node can never match. | |
| 584 virtual RegExpNode* FilterASCII(int depth) { return this; } | |
| 585 // Helper for FilterASCII. | |
| 586 RegExpNode* Uninitialized() { | |
|
ulan
2012/04/25 12:55:28
If it doesn't make big difference in speed/space t
Erik Corry
2012/04/26 08:23:11
Done.
| |
| 587 return reinterpret_cast<RegExpNode*>(&kUninitializedRegExpNodePlaceHolder); | |
| 588 } | |
| 589 | |
| 575 // We want to avoid recalculating the lookahead info, so we store it on the | 590 // We want to avoid recalculating the lookahead info, so we store it on the |
| 576 // node. Only info that is for this node is stored. We can tell that the | 591 // node. Only info that is for this node is stored. We can tell that the |
| 577 // info is for this node when offset == 0, so the information is calculated | 592 // info is for this node when offset == 0, so the information is calculated |
| 578 // relative to this node. | 593 // relative to this node. |
| 579 void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) { | 594 void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) { |
| 580 if (offset == 0) set_bm_info(not_at_start, bm); | 595 if (offset == 0) set_bm_info(not_at_start, bm); |
| 581 } | 596 } |
| 582 | 597 |
| 583 Label* label() { return &label_; } | 598 Label* label() { return &label_; } |
| 584 // If non-generic code is generated for a node (i.e. the node is not at the | 599 // If non-generic code is generated for a node (i.e. the node is not at the |
| 585 // start of the trace) then it cannot be reused. This variable sets a limit | 600 // start of the trace) then it cannot be reused. This variable sets a limit |
| 586 // on how often we allow that to happen before we insist on starting a new | 601 // on how often we allow that to happen before we insist on starting a new |
| 587 // trace and generating generic code for a node that can be reused by flushing | 602 // trace and generating generic code for a node that can be reused by flushing |
| 588 // the deferred actions in the current trace and generating a goto. | 603 // the deferred actions in the current trace and generating a goto. |
| 589 static const int kMaxCopiesCodeGenerated = 10; | 604 static const int kMaxCopiesCodeGenerated = 10; |
| 590 | 605 |
| 591 NodeInfo* info() { return &info_; } | 606 NodeInfo* info() { return &info_; } |
| 592 | 607 |
| 593 BoyerMooreLookahead* bm_info(bool not_at_start) { | 608 BoyerMooreLookahead* bm_info(bool not_at_start) { |
| 594 return bm_info_[not_at_start ? 1 : 0]; | 609 return bm_info_[not_at_start ? 1 : 0]; |
| 595 } | 610 } |
| 596 | 611 |
| 597 protected: | 612 protected: |
| 598 enum LimitResult { DONE, CONTINUE }; | 613 enum LimitResult { DONE, CONTINUE }; |
| 614 RegExpNode* replacement_; | |
| 599 | 615 |
| 600 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); | 616 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); |
| 601 | 617 |
| 602 // Returns a clone of this node initialized using the copy constructor | |
| 603 // of its concrete class. Note that the node may have to be pre- | |
| 604 // processed before it is on a usable state. | |
| 605 virtual RegExpNode* Clone() = 0; | |
| 606 | |
| 607 void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) { | 618 void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) { |
| 608 bm_info_[not_at_start ? 1 : 0] = bm; | 619 bm_info_[not_at_start ? 1 : 0] = bm; |
| 609 } | 620 } |
| 610 | 621 |
| 611 private: | 622 private: |
| 612 static const int kFirstCharBudget = 10; | 623 static const int kFirstCharBudget = 10; |
| 613 Label label_; | 624 Label label_; |
| 614 NodeInfo info_; | 625 NodeInfo info_; |
| 615 // This variable keeps track of how many times code has been generated for | 626 // This variable keeps track of how many times code has been generated for |
| 616 // this node (in different traces). We don't keep track of where the | 627 // this node (in different traces). We don't keep track of where the |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 int to_; | 659 int to_; |
| 649 }; | 660 }; |
| 650 | 661 |
| 651 | 662 |
| 652 class SeqRegExpNode: public RegExpNode { | 663 class SeqRegExpNode: public RegExpNode { |
| 653 public: | 664 public: |
| 654 explicit SeqRegExpNode(RegExpNode* on_success) | 665 explicit SeqRegExpNode(RegExpNode* on_success) |
| 655 : on_success_(on_success) { } | 666 : on_success_(on_success) { } |
| 656 RegExpNode* on_success() { return on_success_; } | 667 RegExpNode* on_success() { return on_success_; } |
| 657 void set_on_success(RegExpNode* node) { on_success_ = node; } | 668 void set_on_success(RegExpNode* node) { on_success_ = node; } |
| 669 virtual RegExpNode* FilterASCII(int depth); | |
| 658 virtual void FillInBMInfo( | 670 virtual void FillInBMInfo( |
| 659 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | 671 int offset, BoyerMooreLookahead* bm, bool not_at_start) { |
| 660 on_success_->FillInBMInfo(offset, bm, not_at_start); | 672 on_success_->FillInBMInfo(offset, bm, not_at_start); |
| 661 if (offset == 0) set_bm_info(not_at_start, bm); | 673 if (offset == 0) set_bm_info(not_at_start, bm); |
| 662 } | 674 } |
| 675 | |
| 676 protected: | |
| 677 RegExpNode* FilterSuccessor(int depth); | |
| 678 | |
| 663 private: | 679 private: |
| 664 RegExpNode* on_success_; | 680 RegExpNode* on_success_; |
| 665 }; | 681 }; |
| 666 | 682 |
| 667 | 683 |
| 668 class ActionNode: public SeqRegExpNode { | 684 class ActionNode: public SeqRegExpNode { |
| 669 public: | 685 public: |
| 670 enum Type { | 686 enum Type { |
| 671 SET_REGISTER, | 687 SET_REGISTER, |
| 672 INCREMENT_REGISTER, | 688 INCREMENT_REGISTER, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 704 int filled_in, | 720 int filled_in, |
| 705 bool not_at_start) { | 721 bool not_at_start) { |
| 706 return on_success()->GetQuickCheckDetails( | 722 return on_success()->GetQuickCheckDetails( |
| 707 details, compiler, filled_in, not_at_start); | 723 details, compiler, filled_in, not_at_start); |
| 708 } | 724 } |
| 709 virtual void FillInBMInfo( | 725 virtual void FillInBMInfo( |
| 710 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 726 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 711 Type type() { return type_; } | 727 Type type() { return type_; } |
| 712 // TODO(erikcorry): We should allow some action nodes in greedy loops. | 728 // TODO(erikcorry): We should allow some action nodes in greedy loops. |
| 713 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | 729 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 714 virtual ActionNode* Clone() { return new ActionNode(*this); } | |
| 715 | 730 |
| 716 private: | 731 private: |
| 717 union { | 732 union { |
| 718 struct { | 733 struct { |
| 719 int reg; | 734 int reg; |
| 720 int value; | 735 int value; |
| 721 } u_store_register; | 736 } u_store_register; |
| 722 struct { | 737 struct { |
| 723 int reg; | 738 int reg; |
| 724 } u_increment_register; | 739 } u_increment_register; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 771 RegExpCompiler* compiler, | 786 RegExpCompiler* compiler, |
| 772 int characters_filled_in, | 787 int characters_filled_in, |
| 773 bool not_at_start); | 788 bool not_at_start); |
| 774 ZoneList<TextElement>* elements() { return elms_; } | 789 ZoneList<TextElement>* elements() { return elms_; } |
| 775 void MakeCaseIndependent(bool is_ascii); | 790 void MakeCaseIndependent(bool is_ascii); |
| 776 virtual int GreedyLoopTextLength(); | 791 virtual int GreedyLoopTextLength(); |
| 777 virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( | 792 virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( |
| 778 RegExpCompiler* compiler); | 793 RegExpCompiler* compiler); |
| 779 virtual void FillInBMInfo( | 794 virtual void FillInBMInfo( |
| 780 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 795 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 781 virtual TextNode* Clone() { | |
| 782 TextNode* result = new TextNode(*this); | |
| 783 result->CalculateOffsets(); | |
| 784 return result; | |
| 785 } | |
| 786 void CalculateOffsets(); | 796 void CalculateOffsets(); |
| 797 virtual RegExpNode* FilterASCII(int depth); | |
| 787 | 798 |
| 788 private: | 799 private: |
| 789 enum TextEmitPassType { | 800 enum TextEmitPassType { |
| 790 NON_ASCII_MATCH, // Check for characters that can't match. | 801 NON_ASCII_MATCH, // Check for characters that can't match. |
| 791 SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. | 802 SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. |
| 792 NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs. | 803 NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs. |
| 793 CASE_CHARACTER_MATCH, // Case-independent single character check. | 804 CASE_CHARACTER_MATCH, // Case-independent single character check. |
| 794 CHARACTER_CLASS_MATCH // Character class. | 805 CHARACTER_CLASS_MATCH // Character class. |
| 795 }; | 806 }; |
| 796 static bool SkipPass(int pass, bool ignore_case); | 807 static bool SkipPass(int pass, bool ignore_case); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 846 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 836 virtual int EatsAtLeast(int still_to_find, | 847 virtual int EatsAtLeast(int still_to_find, |
| 837 int recursion_depth, | 848 int recursion_depth, |
| 838 bool not_at_start); | 849 bool not_at_start); |
| 839 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 850 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 840 RegExpCompiler* compiler, | 851 RegExpCompiler* compiler, |
| 841 int filled_in, | 852 int filled_in, |
| 842 bool not_at_start); | 853 bool not_at_start); |
| 843 virtual void FillInBMInfo( | 854 virtual void FillInBMInfo( |
| 844 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 855 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 845 virtual AssertionNode* Clone() { return new AssertionNode(*this); } | |
| 846 AssertionNodeType type() { return type_; } | 856 AssertionNodeType type() { return type_; } |
| 847 void set_type(AssertionNodeType type) { type_ = type; } | 857 void set_type(AssertionNodeType type) { type_ = type; } |
| 848 | 858 |
| 849 private: | 859 private: |
| 850 void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace); | 860 void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace); |
| 851 enum IfPrevious { kIsNonWord, kIsWord }; | 861 enum IfPrevious { kIsNonWord, kIsWord }; |
| 852 void BacktrackIfPrevious(RegExpCompiler* compiler, | 862 void BacktrackIfPrevious(RegExpCompiler* compiler, |
| 853 Trace* trace, | 863 Trace* trace, |
| 854 IfPrevious backtrack_if_previous); | 864 IfPrevious backtrack_if_previous); |
| 855 AssertionNode(AssertionNodeType t, RegExpNode* on_success) | 865 AssertionNode(AssertionNodeType t, RegExpNode* on_success) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 874 int recursion_depth, | 884 int recursion_depth, |
| 875 bool not_at_start); | 885 bool not_at_start); |
| 876 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 886 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 877 RegExpCompiler* compiler, | 887 RegExpCompiler* compiler, |
| 878 int characters_filled_in, | 888 int characters_filled_in, |
| 879 bool not_at_start) { | 889 bool not_at_start) { |
| 880 return; | 890 return; |
| 881 } | 891 } |
| 882 virtual void FillInBMInfo( | 892 virtual void FillInBMInfo( |
| 883 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 893 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 884 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } | |
| 885 | 894 |
| 886 private: | 895 private: |
| 887 int start_reg_; | 896 int start_reg_; |
| 888 int end_reg_; | 897 int end_reg_; |
| 889 }; | 898 }; |
| 890 | 899 |
| 891 | 900 |
| 892 class EndNode: public RegExpNode { | 901 class EndNode: public RegExpNode { |
| 893 public: | 902 public: |
| 894 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; | 903 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; |
| 895 explicit EndNode(Action action) : action_(action) { } | 904 explicit EndNode(Action action) : action_(action) { } |
| 896 virtual void Accept(NodeVisitor* visitor); | 905 virtual void Accept(NodeVisitor* visitor); |
| 897 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 906 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 898 virtual int EatsAtLeast(int still_to_find, | 907 virtual int EatsAtLeast(int still_to_find, |
| 899 int recursion_depth, | 908 int recursion_depth, |
| 900 bool not_at_start) { return 0; } | 909 bool not_at_start) { return 0; } |
| 901 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 910 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 902 RegExpCompiler* compiler, | 911 RegExpCompiler* compiler, |
| 903 int characters_filled_in, | 912 int characters_filled_in, |
| 904 bool not_at_start) { | 913 bool not_at_start) { |
| 905 // Returning 0 from EatsAtLeast should ensure we never get here. | 914 // Returning 0 from EatsAtLeast should ensure we never get here. |
| 906 UNREACHABLE(); | 915 UNREACHABLE(); |
| 907 } | 916 } |
| 908 virtual void FillInBMInfo( | 917 virtual void FillInBMInfo( |
| 909 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | 918 int offset, BoyerMooreLookahead* bm, bool not_at_start) { |
| 910 // Returning 0 from EatsAtLeast should ensure we never get here. | 919 // Returning 0 from EatsAtLeast should ensure we never get here. |
| 911 UNREACHABLE(); | 920 UNREACHABLE(); |
| 912 } | 921 } |
| 913 virtual EndNode* Clone() { return new EndNode(*this); } | 922 |
| 914 private: | 923 private: |
| 915 Action action_; | 924 Action action_; |
| 916 }; | 925 }; |
| 917 | 926 |
| 918 | 927 |
| 919 class NegativeSubmatchSuccess: public EndNode { | 928 class NegativeSubmatchSuccess: public EndNode { |
| 920 public: | 929 public: |
| 921 NegativeSubmatchSuccess(int stack_pointer_reg, | 930 NegativeSubmatchSuccess(int stack_pointer_reg, |
| 922 int position_reg, | 931 int position_reg, |
| 923 int clear_capture_count, | 932 int clear_capture_count, |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 951 private: | 960 private: |
| 952 int reg_; | 961 int reg_; |
| 953 Relation op_; | 962 Relation op_; |
| 954 int value_; | 963 int value_; |
| 955 }; | 964 }; |
| 956 | 965 |
| 957 | 966 |
| 958 class GuardedAlternative { | 967 class GuardedAlternative { |
| 959 public: | 968 public: |
| 960 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { } | 969 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { } |
| 970 GuardedAlternative(RegExpNode* node, ZoneList<Guard*>* guards) | |
|
ulan
2012/04/25 12:55:28
This seems to be unused.
Erik Corry
2012/04/26 08:23:11
Done.
| |
| 971 : node_(node), guards_(guards) { } | |
| 961 void AddGuard(Guard* guard); | 972 void AddGuard(Guard* guard); |
| 962 RegExpNode* node() { return node_; } | 973 RegExpNode* node() { return node_; } |
| 963 void set_node(RegExpNode* node) { node_ = node; } | 974 void set_node(RegExpNode* node) { node_ = node; } |
| 964 ZoneList<Guard*>* guards() { return guards_; } | 975 ZoneList<Guard*>* guards() { return guards_; } |
| 965 | 976 |
| 966 private: | 977 private: |
| 967 RegExpNode* node_; | 978 RegExpNode* node_; |
| 968 ZoneList<Guard*>* guards_; | 979 ZoneList<Guard*>* guards_; |
| 969 }; | 980 }; |
| 970 | 981 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 990 int EatsAtLeastHelper(int still_to_find, | 1001 int EatsAtLeastHelper(int still_to_find, |
| 991 int recursion_depth, | 1002 int recursion_depth, |
| 992 RegExpNode* ignore_this_node, | 1003 RegExpNode* ignore_this_node, |
| 993 bool not_at_start); | 1004 bool not_at_start); |
| 994 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1005 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 995 RegExpCompiler* compiler, | 1006 RegExpCompiler* compiler, |
| 996 int characters_filled_in, | 1007 int characters_filled_in, |
| 997 bool not_at_start); | 1008 bool not_at_start); |
| 998 virtual void FillInBMInfo( | 1009 virtual void FillInBMInfo( |
| 999 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 1010 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 1000 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } | |
| 1001 | 1011 |
| 1002 bool being_calculated() { return being_calculated_; } | 1012 bool being_calculated() { return being_calculated_; } |
| 1003 bool not_at_start() { return not_at_start_; } | 1013 bool not_at_start() { return not_at_start_; } |
| 1004 void set_not_at_start() { not_at_start_ = true; } | 1014 void set_not_at_start() { not_at_start_ = true; } |
| 1005 void set_being_calculated(bool b) { being_calculated_ = b; } | 1015 void set_being_calculated(bool b) { being_calculated_ = b; } |
| 1006 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } | 1016 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } |
| 1017 virtual RegExpNode* FilterASCII(int depth); | |
| 1007 | 1018 |
| 1008 protected: | 1019 protected: |
| 1009 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); | 1020 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); |
| 1010 ZoneList<GuardedAlternative>* alternatives_; | 1021 ZoneList<GuardedAlternative>* alternatives_; |
| 1011 | 1022 |
| 1012 private: | 1023 private: |
| 1013 friend class DispatchTableConstructor; | 1024 friend class DispatchTableConstructor; |
| 1014 friend class Analysis; | 1025 friend class Analysis; |
| 1015 void GenerateGuard(RegExpMacroAssembler* macro_assembler, | 1026 void GenerateGuard(RegExpMacroAssembler* macro_assembler, |
| 1016 Guard* guard, | 1027 Guard* guard, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1049 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | 1060 int offset, BoyerMooreLookahead* bm, bool not_at_start) { |
| 1050 alternatives_->at(1).node()->FillInBMInfo(offset, bm, not_at_start); | 1061 alternatives_->at(1).node()->FillInBMInfo(offset, bm, not_at_start); |
| 1051 if (offset == 0) set_bm_info(not_at_start, bm); | 1062 if (offset == 0) set_bm_info(not_at_start, bm); |
| 1052 } | 1063 } |
| 1053 // For a negative lookahead we don't emit the quick check for the | 1064 // For a negative lookahead we don't emit the quick check for the |
| 1054 // alternative that is expected to fail. This is because quick check code | 1065 // alternative that is expected to fail. This is because quick check code |
| 1055 // starts by loading enough characters for the alternative that takes fewest | 1066 // starts by loading enough characters for the alternative that takes fewest |
| 1056 // characters, but on a negative lookahead the negative branch did not take | 1067 // characters, but on a negative lookahead the negative branch did not take |
| 1057 // part in that calculation (EatsAtLeast) so the assumptions don't hold. | 1068 // part in that calculation (EatsAtLeast) so the assumptions don't hold. |
| 1058 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } | 1069 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } |
| 1070 virtual RegExpNode* FilterASCII(int depth); | |
| 1059 }; | 1071 }; |
| 1060 | 1072 |
| 1061 | 1073 |
| 1062 class LoopChoiceNode: public ChoiceNode { | 1074 class LoopChoiceNode: public ChoiceNode { |
| 1063 public: | 1075 public: |
| 1064 explicit LoopChoiceNode(bool body_can_be_zero_length) | 1076 explicit LoopChoiceNode(bool body_can_be_zero_length) |
| 1065 : ChoiceNode(2), | 1077 : ChoiceNode(2), |
| 1066 loop_node_(NULL), | 1078 loop_node_(NULL), |
| 1067 continue_node_(NULL), | 1079 continue_node_(NULL), |
| 1068 body_can_be_zero_length_(body_can_be_zero_length) { } | 1080 body_can_be_zero_length_(body_can_be_zero_length) { } |
| 1069 void AddLoopAlternative(GuardedAlternative alt); | 1081 void AddLoopAlternative(GuardedAlternative alt); |
| 1070 void AddContinueAlternative(GuardedAlternative alt); | 1082 void AddContinueAlternative(GuardedAlternative alt); |
| 1071 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1083 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 1072 virtual int EatsAtLeast(int still_to_find, | 1084 virtual int EatsAtLeast(int still_to_find, |
| 1073 int recursion_depth, | 1085 int recursion_depth, |
| 1074 bool not_at_start); | 1086 bool not_at_start); |
| 1075 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1087 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1076 RegExpCompiler* compiler, | 1088 RegExpCompiler* compiler, |
| 1077 int characters_filled_in, | 1089 int characters_filled_in, |
| 1078 bool not_at_start); | 1090 bool not_at_start); |
| 1079 virtual void FillInBMInfo( | 1091 virtual void FillInBMInfo( |
| 1080 int offset, BoyerMooreLookahead* bm, bool not_at_start); | 1092 int offset, BoyerMooreLookahead* bm, bool not_at_start); |
| 1081 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } | |
| 1082 RegExpNode* loop_node() { return loop_node_; } | 1093 RegExpNode* loop_node() { return loop_node_; } |
| 1083 RegExpNode* continue_node() { return continue_node_; } | 1094 RegExpNode* continue_node() { return continue_node_; } |
| 1084 bool body_can_be_zero_length() { return body_can_be_zero_length_; } | 1095 bool body_can_be_zero_length() { return body_can_be_zero_length_; } |
| 1085 virtual void Accept(NodeVisitor* visitor); | 1096 virtual void Accept(NodeVisitor* visitor); |
| 1097 virtual RegExpNode* FilterASCII(int depth); | |
| 1086 | 1098 |
| 1087 private: | 1099 private: |
| 1088 // AddAlternative is made private for loop nodes because alternatives | 1100 // AddAlternative is made private for loop nodes because alternatives |
| 1089 // should not be added freely, we need to keep track of which node | 1101 // should not be added freely, we need to keep track of which node |
| 1090 // goes back to the node itself. | 1102 // goes back to the node itself. |
| 1091 void AddAlternative(GuardedAlternative node) { | 1103 void AddAlternative(GuardedAlternative node) { |
| 1092 ChoiceNode::AddAlternative(node); | 1104 ChoiceNode::AddAlternative(node); |
| 1093 } | 1105 } |
| 1094 | 1106 |
| 1095 RegExpNode* loop_node_; | 1107 RegExpNode* loop_node_; |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1565 int* vector_; | 1577 int* vector_; |
| 1566 int offsets_vector_length_; | 1578 int offsets_vector_length_; |
| 1567 | 1579 |
| 1568 friend class ExternalReference; | 1580 friend class ExternalReference; |
| 1569 }; | 1581 }; |
| 1570 | 1582 |
| 1571 | 1583 |
| 1572 } } // namespace v8::internal | 1584 } } // namespace v8::internal |
| 1573 | 1585 |
| 1574 #endif // V8_JSREGEXP_H_ | 1586 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |