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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 // is not tracked, however. As a conservative approximation we track the | 183 // is not tracked, however. As a conservative approximation we track the |
| 184 // total regexp code compiled including code that has subsequently been freed | 184 // total regexp code compiled including code that has subsequently been freed |
| 185 // and the total executable memory at any point. | 185 // and the total executable memory at any point. |
| 186 static const int kRegExpExecutableMemoryLimit = 16 * MB; | 186 static const int kRegExpExecutableMemoryLimit = 16 * MB; |
| 187 static const int kRegWxpCompiledLimit = 1 * MB; | 187 static const int kRegWxpCompiledLimit = 1 * MB; |
| 188 | 188 |
| 189 private: | 189 private: |
| 190 static String* last_ascii_string_; | 190 static String* last_ascii_string_; |
| 191 static String* two_byte_cached_string_; | 191 static String* two_byte_cached_string_; |
| 192 | 192 |
| 193 static bool CompileIrregexp(Handle<JSRegExp> re, bool is_ascii); | 193 static bool CompileIrregexp( |
| 194 static inline bool EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii); | 194 Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii); |
| 195 static inline bool EnsureCompiledIrregexp( | |
| 196 Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii); | |
| 195 | 197 |
| 196 | 198 |
| 197 // Set the subject cache. The previous string buffer is not deleted, so the | 199 // Set the subject cache. The previous string buffer is not deleted, so the |
| 198 // caller should ensure that it doesn't leak. | 200 // caller should ensure that it doesn't leak. |
| 199 static void SetSubjectCache(String* subject, | 201 static void SetSubjectCache(String* subject, |
| 200 char* utf8_subject, | 202 char* utf8_subject, |
| 201 int uft8_length, | 203 int uft8_length, |
| 202 int character_position, | 204 int character_position, |
| 203 int utf8_position); | 205 int utf8_position); |
| 204 | 206 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 private: | 414 private: |
| 413 // There can't be a static empty set since it allocates its | 415 // There can't be a static empty set since it allocates its |
| 414 // successors in a zone and caches them. | 416 // successors in a zone and caches them. |
| 415 OutSet* empty() { return &empty_; } | 417 OutSet* empty() { return &empty_; } |
| 416 OutSet empty_; | 418 OutSet empty_; |
| 417 ZoneSplayTree<Config>* tree() { return &tree_; } | 419 ZoneSplayTree<Config>* tree() { return &tree_; } |
| 418 ZoneSplayTree<Config> tree_; | 420 ZoneSplayTree<Config> tree_; |
| 419 }; | 421 }; |
| 420 | 422 |
| 421 | 423 |
| 424 class BoyerMooreLookahead { | |
| 425 public: | |
| 426 BoyerMooreLookahead(int length, int map_length, RegExpCompiler* compiler); | |
|
ulan
2012/03/30 16:54:51
We need comments for this class. In particular for
| |
| 427 | |
| 428 int length() { return length_; } | |
| 429 int max_char() { return max_char_; } | |
| 430 RegExpCompiler* compiler() { return compiler_; } | |
| 431 | |
| 432 static const int kTooManyCharacters = 32; | |
| 433 | |
| 434 int Count(int map_number) { | |
| 435 ZoneList<bool>* map = bitmaps_->at(map_number); | |
| 436 if (map == NULL) return map_length_; | |
| 437 int count = 0; | |
| 438 for (int i = 0; i < map_length_; i++) { | |
| 439 if (map->at(i)) count++; | |
| 440 } | |
| 441 return count; | |
| 442 } | |
| 443 | |
| 444 void Set(int map_number, int character) { | |
| 445 if (character > max_char_) return; | |
| 446 ZoneList<bool>* map = bitmaps_->at(map_number); | |
| 447 if (map == NULL) return; | |
| 448 map->at(character & (map_length_ - 1)) = true; | |
| 449 } | |
| 450 | |
| 451 void SetAll(int map_number) { | |
| 452 bitmaps_->at(map_number) = NULL; | |
| 453 } | |
| 454 | |
| 455 void SetRest(int from_map) { | |
| 456 for (int i = from_map; i < length_; i++) SetAll(i); | |
| 457 } | |
| 458 bool EmitSkipInstructions(RegExpMacroAssembler* masm); | |
| 459 | |
| 460 private: | |
| 461 int length_; | |
| 462 int map_length_; | |
| 463 RegExpCompiler* compiler_; | |
| 464 int max_char_; | |
| 465 ZoneList<ZoneList<bool>*>* bitmaps_; | |
| 466 | |
| 467 bool TooVague(int offset, int limit); | |
| 468 int GetSkipTable(int max_lookahead, Handle<ByteArray> boolean_skip_table); | |
| 469 bool FindWorthwhileInterval(int* from, int* to); | |
| 470 }; | |
| 471 | |
| 472 | |
| 422 #define FOR_EACH_NODE_TYPE(VISIT) \ | 473 #define FOR_EACH_NODE_TYPE(VISIT) \ |
| 423 VISIT(End) \ | 474 VISIT(End) \ |
| 424 VISIT(Action) \ | 475 VISIT(Action) \ |
| 425 VISIT(Choice) \ | 476 VISIT(Choice) \ |
| 426 VISIT(BackReference) \ | 477 VISIT(BackReference) \ |
| 427 VISIT(Assertion) \ | 478 VISIT(Assertion) \ |
| 428 VISIT(Text) | 479 VISIT(Text) |
| 429 | 480 |
| 430 | 481 |
| 431 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ | 482 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 // For a given number of characters this returns a mask and a value. The | 679 // For a given number of characters this returns a mask and a value. The |
| 629 // next n characters are anded with the mask and compared with the value. | 680 // next n characters are anded with the mask and compared with the value. |
| 630 // A comparison failure indicates the node cannot match the next n characters. | 681 // A comparison failure indicates the node cannot match the next n characters. |
| 631 // A comparison success indicates the node may match. | 682 // A comparison success indicates the node may match. |
| 632 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 683 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 633 RegExpCompiler* compiler, | 684 RegExpCompiler* compiler, |
| 634 int characters_filled_in, | 685 int characters_filled_in, |
| 635 bool not_at_start) = 0; | 686 bool not_at_start) = 0; |
| 636 static const int kNodeIsTooComplexForGreedyLoops = -1; | 687 static const int kNodeIsTooComplexForGreedyLoops = -1; |
| 637 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | 688 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 689 // Only returns the successor for a text node of length 1 that matches any | |
| 690 // character and that has no guards on it. | |
| 691 virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( | |
| 692 RegExpCompiler* compiler) { | |
| 693 return NULL; | |
| 694 } | |
| 695 | |
| 696 // Collects information on the possible code units (mod 128) that can match if | |
| 697 // we look forward. This is used for a Boyer-Moore-like string searching | |
| 698 // implementation. TODO(erikcorry): This should share more code with | |
| 699 // EatsAtLeast, GetQuickCheckDetails and ComputeFirstCharacterSet. | |
| 700 virtual void FillInBMInfo( | |
| 701 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | |
| 702 UNREACHABLE(); | |
| 703 } | |
| 704 | |
| 638 Label* label() { return &label_; } | 705 Label* label() { return &label_; } |
| 639 // If non-generic code is generated for a node (i.e. the node is not at the | 706 // If non-generic code is generated for a node (i.e. the node is not at the |
| 640 // start of the trace) then it cannot be reused. This variable sets a limit | 707 // start of the trace) then it cannot be reused. This variable sets a limit |
| 641 // on how often we allow that to happen before we insist on starting a new | 708 // on how often we allow that to happen before we insist on starting a new |
| 642 // trace and generating generic code for a node that can be reused by flushing | 709 // trace and generating generic code for a node that can be reused by flushing |
| 643 // the deferred actions in the current trace and generating a goto. | 710 // the deferred actions in the current trace and generating a goto. |
| 644 static const int kMaxCopiesCodeGenerated = 10; | 711 static const int kMaxCopiesCodeGenerated = 10; |
| 645 | 712 |
| 646 NodeInfo* info() { return &info_; } | 713 NodeInfo* info() { return &info_; } |
| 647 | 714 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 int to_; | 807 int to_; |
| 741 }; | 808 }; |
| 742 | 809 |
| 743 | 810 |
| 744 class SeqRegExpNode: public RegExpNode { | 811 class SeqRegExpNode: public RegExpNode { |
| 745 public: | 812 public: |
| 746 explicit SeqRegExpNode(RegExpNode* on_success) | 813 explicit SeqRegExpNode(RegExpNode* on_success) |
| 747 : on_success_(on_success) { } | 814 : on_success_(on_success) { } |
| 748 RegExpNode* on_success() { return on_success_; } | 815 RegExpNode* on_success() { return on_success_; } |
| 749 void set_on_success(RegExpNode* node) { on_success_ = node; } | 816 void set_on_success(RegExpNode* node) { on_success_ = node; } |
| 817 virtual void FillInBMInfo( | |
| 818 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | |
| 819 on_success_->FillInBMInfo(offset, bm, not_at_start); | |
| 820 } | |
| 750 private: | 821 private: |
| 751 RegExpNode* on_success_; | 822 RegExpNode* on_success_; |
| 752 }; | 823 }; |
| 753 | 824 |
| 754 | 825 |
| 755 class ActionNode: public SeqRegExpNode { | 826 class ActionNode: public SeqRegExpNode { |
| 756 public: | 827 public: |
| 757 enum Type { | 828 enum Type { |
| 758 SET_REGISTER, | 829 SET_REGISTER, |
| 759 INCREMENT_REGISTER, | 830 INCREMENT_REGISTER, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 786 virtual int EatsAtLeast(int still_to_find, | 857 virtual int EatsAtLeast(int still_to_find, |
| 787 int recursion_depth, | 858 int recursion_depth, |
| 788 bool not_at_start); | 859 bool not_at_start); |
| 789 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 860 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 790 RegExpCompiler* compiler, | 861 RegExpCompiler* compiler, |
| 791 int filled_in, | 862 int filled_in, |
| 792 bool not_at_start) { | 863 bool not_at_start) { |
| 793 return on_success()->GetQuickCheckDetails( | 864 return on_success()->GetQuickCheckDetails( |
| 794 details, compiler, filled_in, not_at_start); | 865 details, compiler, filled_in, not_at_start); |
| 795 } | 866 } |
| 867 virtual void FillInBMInfo( | |
| 868 int offset, BoyerMooreLookahead* bm, bool not_at_start); | |
| 796 Type type() { return type_; } | 869 Type type() { return type_; } |
| 797 // TODO(erikcorry): We should allow some action nodes in greedy loops. | 870 // TODO(erikcorry): We should allow some action nodes in greedy loops. |
| 798 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | 871 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 799 virtual ActionNode* Clone() { return new ActionNode(*this); } | 872 virtual ActionNode* Clone() { return new ActionNode(*this); } |
| 800 virtual int ComputeFirstCharacterSet(int budget); | 873 virtual int ComputeFirstCharacterSet(int budget); |
| 801 | 874 |
| 802 private: | 875 private: |
| 803 union { | 876 union { |
| 804 struct { | 877 struct { |
| 805 int reg; | 878 int reg; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 virtual int EatsAtLeast(int still_to_find, | 926 virtual int EatsAtLeast(int still_to_find, |
| 854 int recursion_depth, | 927 int recursion_depth, |
| 855 bool not_at_start); | 928 bool not_at_start); |
| 856 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 929 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 857 RegExpCompiler* compiler, | 930 RegExpCompiler* compiler, |
| 858 int characters_filled_in, | 931 int characters_filled_in, |
| 859 bool not_at_start); | 932 bool not_at_start); |
| 860 ZoneList<TextElement>* elements() { return elms_; } | 933 ZoneList<TextElement>* elements() { return elms_; } |
| 861 void MakeCaseIndependent(bool is_ascii); | 934 void MakeCaseIndependent(bool is_ascii); |
| 862 virtual int GreedyLoopTextLength(); | 935 virtual int GreedyLoopTextLength(); |
| 936 virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( | |
| 937 RegExpCompiler* compiler); | |
| 938 virtual void FillInBMInfo( | |
| 939 int offset, BoyerMooreLookahead* bm, bool not_at_start); | |
| 863 virtual TextNode* Clone() { | 940 virtual TextNode* Clone() { |
| 864 TextNode* result = new TextNode(*this); | 941 TextNode* result = new TextNode(*this); |
| 865 result->CalculateOffsets(); | 942 result->CalculateOffsets(); |
| 866 return result; | 943 return result; |
| 867 } | 944 } |
| 868 void CalculateOffsets(); | 945 void CalculateOffsets(); |
| 869 virtual int ComputeFirstCharacterSet(int budget); | 946 virtual int ComputeFirstCharacterSet(int budget); |
| 870 | 947 |
| 871 private: | 948 private: |
| 872 enum TextEmitPassType { | 949 enum TextEmitPassType { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 921 } | 998 } |
| 922 virtual void Accept(NodeVisitor* visitor); | 999 virtual void Accept(NodeVisitor* visitor); |
| 923 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1000 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 924 virtual int EatsAtLeast(int still_to_find, | 1001 virtual int EatsAtLeast(int still_to_find, |
| 925 int recursion_depth, | 1002 int recursion_depth, |
| 926 bool not_at_start); | 1003 bool not_at_start); |
| 927 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1004 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 928 RegExpCompiler* compiler, | 1005 RegExpCompiler* compiler, |
| 929 int filled_in, | 1006 int filled_in, |
| 930 bool not_at_start); | 1007 bool not_at_start); |
| 1008 virtual void FillInBMInfo( | |
| 1009 int offset, BoyerMooreLookahead* bm, bool not_at_start); | |
| 931 virtual int ComputeFirstCharacterSet(int budget); | 1010 virtual int ComputeFirstCharacterSet(int budget); |
| 932 virtual AssertionNode* Clone() { return new AssertionNode(*this); } | 1011 virtual AssertionNode* Clone() { return new AssertionNode(*this); } |
| 933 AssertionNodeType type() { return type_; } | 1012 AssertionNodeType type() { return type_; } |
| 934 void set_type(AssertionNodeType type) { type_ = type; } | 1013 void set_type(AssertionNodeType type) { type_ = type; } |
| 935 | 1014 |
| 936 private: | 1015 private: |
| 937 AssertionNode(AssertionNodeType t, RegExpNode* on_success) | 1016 AssertionNode(AssertionNodeType t, RegExpNode* on_success) |
| 938 : SeqRegExpNode(on_success), type_(t) { } | 1017 : SeqRegExpNode(on_success), type_(t) { } |
| 939 AssertionNodeType type_; | 1018 AssertionNodeType type_; |
| 940 }; | 1019 }; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 954 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1033 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 955 virtual int EatsAtLeast(int still_to_find, | 1034 virtual int EatsAtLeast(int still_to_find, |
| 956 int recursion_depth, | 1035 int recursion_depth, |
| 957 bool not_at_start); | 1036 bool not_at_start); |
| 958 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1037 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 959 RegExpCompiler* compiler, | 1038 RegExpCompiler* compiler, |
| 960 int characters_filled_in, | 1039 int characters_filled_in, |
| 961 bool not_at_start) { | 1040 bool not_at_start) { |
| 962 return; | 1041 return; |
| 963 } | 1042 } |
| 1043 virtual void FillInBMInfo( | |
| 1044 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | |
| 1045 // Working out the set of characters that a backreference can match is too | |
| 1046 // hard, so we just say that any character can match. | |
| 1047 bm->SetRest(offset); | |
| 1048 } | |
| 964 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } | 1049 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } |
| 965 virtual int ComputeFirstCharacterSet(int budget); | 1050 virtual int ComputeFirstCharacterSet(int budget); |
| 966 | 1051 |
| 967 private: | 1052 private: |
| 968 int start_reg_; | 1053 int start_reg_; |
| 969 int end_reg_; | 1054 int end_reg_; |
| 970 }; | 1055 }; |
| 971 | 1056 |
| 972 | 1057 |
| 973 class EndNode: public RegExpNode { | 1058 class EndNode: public RegExpNode { |
| 974 public: | 1059 public: |
| 975 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; | 1060 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; |
| 976 explicit EndNode(Action action) : action_(action) { } | 1061 explicit EndNode(Action action) : action_(action) { } |
| 977 virtual void Accept(NodeVisitor* visitor); | 1062 virtual void Accept(NodeVisitor* visitor); |
| 978 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1063 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 979 virtual int EatsAtLeast(int still_to_find, | 1064 virtual int EatsAtLeast(int still_to_find, |
| 980 int recursion_depth, | 1065 int recursion_depth, |
| 981 bool not_at_start) { return 0; } | 1066 bool not_at_start) { return 0; } |
| 982 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1067 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 983 RegExpCompiler* compiler, | 1068 RegExpCompiler* compiler, |
| 984 int characters_filled_in, | 1069 int characters_filled_in, |
| 985 bool not_at_start) { | 1070 bool not_at_start) { |
| 986 // Returning 0 from EatsAtLeast should ensure we never get here. | 1071 // Returning 0 from EatsAtLeast should ensure we never get here. |
| 987 UNREACHABLE(); | 1072 UNREACHABLE(); |
| 988 } | 1073 } |
| 1074 virtual void FillInBMInfo( | |
| 1075 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | |
| 1076 // Returning 0 from EatsAtLeast should ensure we never get here. | |
| 1077 UNREACHABLE(); | |
| 1078 } | |
| 989 virtual EndNode* Clone() { return new EndNode(*this); } | 1079 virtual EndNode* Clone() { return new EndNode(*this); } |
| 990 private: | 1080 private: |
| 991 Action action_; | 1081 Action action_; |
| 992 }; | 1082 }; |
| 993 | 1083 |
| 994 | 1084 |
| 995 class NegativeSubmatchSuccess: public EndNode { | 1085 class NegativeSubmatchSuccess: public EndNode { |
| 996 public: | 1086 public: |
| 997 NegativeSubmatchSuccess(int stack_pointer_reg, | 1087 NegativeSubmatchSuccess(int stack_pointer_reg, |
| 998 int position_reg, | 1088 int position_reg, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 int recursion_depth, | 1154 int recursion_depth, |
| 1065 bool not_at_start); | 1155 bool not_at_start); |
| 1066 int EatsAtLeastHelper(int still_to_find, | 1156 int EatsAtLeastHelper(int still_to_find, |
| 1067 int recursion_depth, | 1157 int recursion_depth, |
| 1068 RegExpNode* ignore_this_node, | 1158 RegExpNode* ignore_this_node, |
| 1069 bool not_at_start); | 1159 bool not_at_start); |
| 1070 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1160 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1071 RegExpCompiler* compiler, | 1161 RegExpCompiler* compiler, |
| 1072 int characters_filled_in, | 1162 int characters_filled_in, |
| 1073 bool not_at_start); | 1163 bool not_at_start); |
| 1164 virtual void FillInBMInfo( | |
| 1165 int offset, BoyerMooreLookahead* bm, bool not_at_start); | |
| 1074 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } | 1166 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } |
| 1075 | 1167 |
| 1076 bool being_calculated() { return being_calculated_; } | 1168 bool being_calculated() { return being_calculated_; } |
| 1077 bool not_at_start() { return not_at_start_; } | 1169 bool not_at_start() { return not_at_start_; } |
| 1078 void set_not_at_start() { not_at_start_ = true; } | 1170 void set_not_at_start() { not_at_start_ = true; } |
| 1079 void set_being_calculated(bool b) { being_calculated_ = b; } | 1171 void set_being_calculated(bool b) { being_calculated_ = b; } |
| 1080 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } | 1172 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } |
| 1081 | 1173 |
| 1082 protected: | 1174 protected: |
| 1083 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); | 1175 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); |
| 1084 ZoneList<GuardedAlternative>* alternatives_; | 1176 ZoneList<GuardedAlternative>* alternatives_; |
| 1085 | 1177 |
| 1086 private: | 1178 private: |
| 1087 friend class DispatchTableConstructor; | 1179 friend class DispatchTableConstructor; |
| 1088 friend class Analysis; | 1180 friend class Analysis; |
| 1089 void GenerateGuard(RegExpMacroAssembler* macro_assembler, | 1181 void GenerateGuard(RegExpMacroAssembler* macro_assembler, |
| 1090 Guard* guard, | 1182 Guard* guard, |
| 1091 Trace* trace); | 1183 Trace* trace); |
| 1092 int CalculatePreloadCharacters(RegExpCompiler* compiler, bool not_at_start); | 1184 int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least); |
| 1093 void EmitOutOfLineContinuation(RegExpCompiler* compiler, | 1185 void EmitOutOfLineContinuation(RegExpCompiler* compiler, |
| 1094 Trace* trace, | 1186 Trace* trace, |
| 1095 GuardedAlternative alternative, | 1187 GuardedAlternative alternative, |
| 1096 AlternativeGeneration* alt_gen, | 1188 AlternativeGeneration* alt_gen, |
| 1097 int preload_characters, | 1189 int preload_characters, |
| 1098 bool next_expects_preload); | 1190 bool next_expects_preload); |
| 1099 DispatchTable* table_; | 1191 DispatchTable* table_; |
| 1100 // If true, this node is never checked at the start of the input. | 1192 // If true, this node is never checked at the start of the input. |
| 1101 // Allows a new trace to start with at_start() set to false. | 1193 // Allows a new trace to start with at_start() set to false. |
| 1102 bool not_at_start_; | 1194 bool not_at_start_; |
| 1103 bool being_calculated_; | 1195 bool being_calculated_; |
| 1104 }; | 1196 }; |
| 1105 | 1197 |
| 1106 | 1198 |
| 1107 class NegativeLookaheadChoiceNode: public ChoiceNode { | 1199 class NegativeLookaheadChoiceNode: public ChoiceNode { |
| 1108 public: | 1200 public: |
| 1109 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, | 1201 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, |
| 1110 GuardedAlternative then_do_this) | 1202 GuardedAlternative then_do_this) |
| 1111 : ChoiceNode(2) { | 1203 : ChoiceNode(2) { |
| 1112 AddAlternative(this_must_fail); | 1204 AddAlternative(this_must_fail); |
| 1113 AddAlternative(then_do_this); | 1205 AddAlternative(then_do_this); |
| 1114 } | 1206 } |
| 1115 virtual int EatsAtLeast(int still_to_find, | 1207 virtual int EatsAtLeast(int still_to_find, |
| 1116 int recursion_depth, | 1208 int recursion_depth, |
| 1117 bool not_at_start); | 1209 bool not_at_start); |
| 1118 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1210 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1119 RegExpCompiler* compiler, | 1211 RegExpCompiler* compiler, |
| 1120 int characters_filled_in, | 1212 int characters_filled_in, |
| 1121 bool not_at_start); | 1213 bool not_at_start); |
| 1214 virtual void FillInBMInfo( | |
| 1215 int offset, BoyerMooreLookahead* bm, bool not_at_start) { | |
| 1216 alternatives_->at(1).node()->FillInBMInfo(offset, bm, not_at_start); | |
| 1217 } | |
| 1122 // For a negative lookahead we don't emit the quick check for the | 1218 // For a negative lookahead we don't emit the quick check for the |
| 1123 // alternative that is expected to fail. This is because quick check code | 1219 // alternative that is expected to fail. This is because quick check code |
| 1124 // starts by loading enough characters for the alternative that takes fewest | 1220 // starts by loading enough characters for the alternative that takes fewest |
| 1125 // characters, but on a negative lookahead the negative branch did not take | 1221 // characters, but on a negative lookahead the negative branch did not take |
| 1126 // part in that calculation (EatsAtLeast) so the assumptions don't hold. | 1222 // part in that calculation (EatsAtLeast) so the assumptions don't hold. |
| 1127 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } | 1223 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } |
| 1128 virtual int ComputeFirstCharacterSet(int budget); | 1224 virtual int ComputeFirstCharacterSet(int budget); |
| 1129 }; | 1225 }; |
| 1130 | 1226 |
| 1131 | 1227 |
| 1132 class LoopChoiceNode: public ChoiceNode { | 1228 class LoopChoiceNode: public ChoiceNode { |
| 1133 public: | 1229 public: |
| 1134 explicit LoopChoiceNode(bool body_can_be_zero_length) | 1230 explicit LoopChoiceNode(bool body_can_be_zero_length) |
| 1135 : ChoiceNode(2), | 1231 : ChoiceNode(2), |
| 1136 loop_node_(NULL), | 1232 loop_node_(NULL), |
| 1137 continue_node_(NULL), | 1233 continue_node_(NULL), |
| 1138 body_can_be_zero_length_(body_can_be_zero_length) { } | 1234 body_can_be_zero_length_(body_can_be_zero_length) { } |
| 1139 void AddLoopAlternative(GuardedAlternative alt); | 1235 void AddLoopAlternative(GuardedAlternative alt); |
| 1140 void AddContinueAlternative(GuardedAlternative alt); | 1236 void AddContinueAlternative(GuardedAlternative alt); |
| 1141 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1237 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 1142 virtual int EatsAtLeast(int still_to_find, | 1238 virtual int EatsAtLeast(int still_to_find, |
| 1143 int recursion_depth, | 1239 int recursion_depth, |
| 1144 bool not_at_start); | 1240 bool not_at_start); |
| 1145 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1241 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1146 RegExpCompiler* compiler, | 1242 RegExpCompiler* compiler, |
| 1147 int characters_filled_in, | 1243 int characters_filled_in, |
| 1148 bool not_at_start); | 1244 bool not_at_start); |
| 1245 virtual void FillInBMInfo( | |
| 1246 int offset, BoyerMooreLookahead* bm, bool not_at_start); | |
| 1149 virtual int ComputeFirstCharacterSet(int budget); | 1247 virtual int ComputeFirstCharacterSet(int budget); |
| 1150 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } | 1248 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } |
| 1151 RegExpNode* loop_node() { return loop_node_; } | 1249 RegExpNode* loop_node() { return loop_node_; } |
| 1152 RegExpNode* continue_node() { return continue_node_; } | 1250 RegExpNode* continue_node() { return continue_node_; } |
| 1153 bool body_can_be_zero_length() { return body_can_be_zero_length_; } | 1251 bool body_can_be_zero_length() { return body_can_be_zero_length_; } |
| 1154 virtual void Accept(NodeVisitor* visitor); | 1252 virtual void Accept(NodeVisitor* visitor); |
| 1155 | 1253 |
| 1156 private: | 1254 private: |
| 1157 // AddAlternative is made private for loop nodes because alternatives | 1255 // AddAlternative is made private for loop nodes because alternatives |
| 1158 // should not be added freely, we need to keep track of which node | 1256 // should not be added freely, we need to keep track of which node |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1451 num_registers(registers) {} | 1549 num_registers(registers) {} |
| 1452 const char* error_message; | 1550 const char* error_message; |
| 1453 Object* code; | 1551 Object* code; |
| 1454 int num_registers; | 1552 int num_registers; |
| 1455 }; | 1553 }; |
| 1456 | 1554 |
| 1457 static CompilationResult Compile(RegExpCompileData* input, | 1555 static CompilationResult Compile(RegExpCompileData* input, |
| 1458 bool ignore_case, | 1556 bool ignore_case, |
| 1459 bool multiline, | 1557 bool multiline, |
| 1460 Handle<String> pattern, | 1558 Handle<String> pattern, |
| 1559 Handle<String> sample_subject, | |
| 1461 bool is_ascii); | 1560 bool is_ascii); |
| 1462 | 1561 |
| 1463 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); | 1562 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); |
| 1464 }; | 1563 }; |
| 1465 | 1564 |
| 1466 | 1565 |
| 1467 class OffsetsVector { | 1566 class OffsetsVector { |
| 1468 public: | 1567 public: |
| 1469 inline OffsetsVector(int num_registers, Isolate* isolate) | 1568 inline OffsetsVector(int num_registers, Isolate* isolate) |
| 1470 : offsets_vector_length_(num_registers) { | 1569 : offsets_vector_length_(num_registers) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1493 int* vector_; | 1592 int* vector_; |
| 1494 int offsets_vector_length_; | 1593 int offsets_vector_length_; |
| 1495 | 1594 |
| 1496 friend class ExternalReference; | 1595 friend class ExternalReference; |
| 1497 }; | 1596 }; |
| 1498 | 1597 |
| 1499 | 1598 |
| 1500 } } // namespace v8::internal | 1599 } } // namespace v8::internal |
| 1501 | 1600 |
| 1502 #endif // V8_JSREGEXP_H_ | 1601 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |