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 |