| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 SET_REGISTER, | 712 SET_REGISTER, |
| 713 INCREMENT_REGISTER, | 713 INCREMENT_REGISTER, |
| 714 STORE_POSITION, | 714 STORE_POSITION, |
| 715 BEGIN_SUBMATCH, | 715 BEGIN_SUBMATCH, |
| 716 POSITIVE_SUBMATCH_SUCCESS, | 716 POSITIVE_SUBMATCH_SUCCESS, |
| 717 EMPTY_MATCH_CHECK, | 717 EMPTY_MATCH_CHECK, |
| 718 CLEAR_CAPTURES | 718 CLEAR_CAPTURES |
| 719 }; | 719 }; |
| 720 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); | 720 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); |
| 721 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); | 721 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); |
| 722 static ActionNode* StorePosition(int reg, RegExpNode* on_success); | 722 static ActionNode* StorePosition(int reg, |
| 723 bool is_capture, |
| 724 RegExpNode* on_success); |
| 723 static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success); | 725 static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success); |
| 724 static ActionNode* BeginSubmatch(int stack_pointer_reg, | 726 static ActionNode* BeginSubmatch(int stack_pointer_reg, |
| 725 int position_reg, | 727 int position_reg, |
| 726 RegExpNode* on_success); | 728 RegExpNode* on_success); |
| 727 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg, | 729 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg, |
| 728 int restore_reg, | 730 int restore_reg, |
| 731 int clear_capture_count, |
| 732 int clear_capture_from, |
| 729 RegExpNode* on_success); | 733 RegExpNode* on_success); |
| 730 static ActionNode* EmptyMatchCheck(int start_register, | 734 static ActionNode* EmptyMatchCheck(int start_register, |
| 731 int repetition_register, | 735 int repetition_register, |
| 732 int repetition_limit, | 736 int repetition_limit, |
| 733 RegExpNode* on_success); | 737 RegExpNode* on_success); |
| 734 virtual void Accept(NodeVisitor* visitor); | 738 virtual void Accept(NodeVisitor* visitor); |
| 735 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); | 739 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); |
| 736 virtual int EatsAtLeast(int recursion_depth); | 740 virtual int EatsAtLeast(int recursion_depth); |
| 737 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 741 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 738 RegExpCompiler* compiler, | 742 RegExpCompiler* compiler, |
| 739 int filled_in) { | 743 int filled_in) { |
| 740 return on_success()->GetQuickCheckDetails(details, compiler, filled_in); | 744 return on_success()->GetQuickCheckDetails(details, compiler, filled_in); |
| 741 } | 745 } |
| 742 Type type() { return type_; } | 746 Type type() { return type_; } |
| 743 // TODO(erikcorry): We should allow some action nodes in greedy loops. | 747 // TODO(erikcorry): We should allow some action nodes in greedy loops. |
| 744 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | 748 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 745 virtual ActionNode* Clone() { return new ActionNode(*this); } | 749 virtual ActionNode* Clone() { return new ActionNode(*this); } |
| 746 | 750 |
| 747 private: | 751 private: |
| 748 union { | 752 union { |
| 749 struct { | 753 struct { |
| 750 int reg; | 754 int reg; |
| 751 int value; | 755 int value; |
| 752 } u_store_register; | 756 } u_store_register; |
| 753 struct { | 757 struct { |
| 754 int reg; | 758 int reg; |
| 755 } u_increment_register; | 759 } u_increment_register; |
| 756 struct { | 760 struct { |
| 757 int reg; | 761 int reg; |
| 762 bool is_capture; |
| 758 } u_position_register; | 763 } u_position_register; |
| 759 struct { | 764 struct { |
| 760 int stack_pointer_register; | 765 int stack_pointer_register; |
| 761 int current_position_register; | 766 int current_position_register; |
| 767 int clear_register_count; |
| 768 int clear_register_from; |
| 762 } u_submatch; | 769 } u_submatch; |
| 763 struct { | 770 struct { |
| 764 int start_register; | 771 int start_register; |
| 765 int repetition_register; | 772 int repetition_register; |
| 766 int repetition_limit; | 773 int repetition_limit; |
| 767 } u_empty_match_check; | 774 } u_empty_match_check; |
| 768 struct { | 775 struct { |
| 769 int range_from; | 776 int range_from; |
| 770 int range_to; | 777 int range_to; |
| 771 } u_clear_captures; | 778 } u_clear_captures; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 } | 913 } |
| 907 virtual EndNode* Clone() { return new EndNode(*this); } | 914 virtual EndNode* Clone() { return new EndNode(*this); } |
| 908 | 915 |
| 909 private: | 916 private: |
| 910 Action action_; | 917 Action action_; |
| 911 }; | 918 }; |
| 912 | 919 |
| 913 | 920 |
| 914 class NegativeSubmatchSuccess: public EndNode { | 921 class NegativeSubmatchSuccess: public EndNode { |
| 915 public: | 922 public: |
| 916 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg) | 923 NegativeSubmatchSuccess(int stack_pointer_reg, |
| 924 int position_reg, |
| 925 int clear_capture_count, |
| 926 int clear_capture_start) |
| 917 : EndNode(NEGATIVE_SUBMATCH_SUCCESS), | 927 : EndNode(NEGATIVE_SUBMATCH_SUCCESS), |
| 918 stack_pointer_register_(stack_pointer_reg), | 928 stack_pointer_register_(stack_pointer_reg), |
| 919 current_position_register_(position_reg) { } | 929 current_position_register_(position_reg), |
| 930 clear_capture_count_(clear_capture_count), |
| 931 clear_capture_start_(clear_capture_start) { } |
| 920 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); | 932 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); |
| 921 | 933 |
| 922 private: | 934 private: |
| 923 int stack_pointer_register_; | 935 int stack_pointer_register_; |
| 924 int current_position_register_; | 936 int current_position_register_; |
| 937 int clear_capture_count_; |
| 938 int clear_capture_start_; |
| 925 }; | 939 }; |
| 926 | 940 |
| 927 | 941 |
| 928 class Guard: public ZoneObject { | 942 class Guard: public ZoneObject { |
| 929 public: | 943 public: |
| 930 enum Relation { LT, GEQ }; | 944 enum Relation { LT, GEQ }; |
| 931 Guard(int reg, Relation op, int value) | 945 Guard(int reg, Relation op, int value) |
| 932 : reg_(reg), | 946 : reg_(reg), |
| 933 op_(op), | 947 op_(op), |
| 934 value_(value) { } | 948 value_(value) { } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 bool Mentions(int reg); | 1094 bool Mentions(int reg); |
| 1081 int reg() { return reg_; } | 1095 int reg() { return reg_; } |
| 1082 ActionNode::Type type() { return type_; } | 1096 ActionNode::Type type() { return type_; } |
| 1083 private: | 1097 private: |
| 1084 ActionNode::Type type_; | 1098 ActionNode::Type type_; |
| 1085 int reg_; | 1099 int reg_; |
| 1086 DeferredAction* next_; | 1100 DeferredAction* next_; |
| 1087 friend class Trace; | 1101 friend class Trace; |
| 1088 }; | 1102 }; |
| 1089 | 1103 |
| 1090 class DeferredCapture: public DeferredAction { | 1104 class DeferredCapture : public DeferredAction { |
| 1091 public: | 1105 public: |
| 1092 DeferredCapture(int reg, Trace* trace) | 1106 DeferredCapture(int reg, bool is_capture, Trace* trace) |
| 1093 : DeferredAction(ActionNode::STORE_POSITION, reg), | 1107 : DeferredAction(ActionNode::STORE_POSITION, reg), |
| 1094 cp_offset_(trace->cp_offset()) { } | 1108 cp_offset_(trace->cp_offset()) { } |
| 1095 int cp_offset() { return cp_offset_; } | 1109 int cp_offset() { return cp_offset_; } |
| 1110 bool is_capture() { return is_capture_; } |
| 1096 private: | 1111 private: |
| 1097 int cp_offset_; | 1112 int cp_offset_; |
| 1113 bool is_capture_; |
| 1098 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } | 1114 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } |
| 1099 }; | 1115 }; |
| 1100 | 1116 |
| 1101 class DeferredSetRegister :public DeferredAction { | 1117 class DeferredSetRegister : public DeferredAction { |
| 1102 public: | 1118 public: |
| 1103 DeferredSetRegister(int reg, int value) | 1119 DeferredSetRegister(int reg, int value) |
| 1104 : DeferredAction(ActionNode::SET_REGISTER, reg), | 1120 : DeferredAction(ActionNode::SET_REGISTER, reg), |
| 1105 value_(value) { } | 1121 value_(value) { } |
| 1106 int value() { return value_; } | 1122 int value() { return value_; } |
| 1107 private: | 1123 private: |
| 1108 int value_; | 1124 int value_; |
| 1109 }; | 1125 }; |
| 1110 | 1126 |
| 1111 class DeferredClearCaptures : public DeferredAction { | 1127 class DeferredClearCaptures : public DeferredAction { |
| 1112 public: | 1128 public: |
| 1113 explicit DeferredClearCaptures(Interval range) | 1129 explicit DeferredClearCaptures(Interval range) |
| 1114 : DeferredAction(ActionNode::CLEAR_CAPTURES, -1), | 1130 : DeferredAction(ActionNode::CLEAR_CAPTURES, -1), |
| 1115 range_(range) { } | 1131 range_(range) { } |
| 1116 Interval range() { return range_; } | 1132 Interval range() { return range_; } |
| 1117 private: | 1133 private: |
| 1118 Interval range_; | 1134 Interval range_; |
| 1119 }; | 1135 }; |
| 1120 | 1136 |
| 1121 class DeferredIncrementRegister: public DeferredAction { | 1137 class DeferredIncrementRegister : public DeferredAction { |
| 1122 public: | 1138 public: |
| 1123 explicit DeferredIncrementRegister(int reg) | 1139 explicit DeferredIncrementRegister(int reg) |
| 1124 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } | 1140 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } |
| 1125 }; | 1141 }; |
| 1126 | 1142 |
| 1127 Trace() | 1143 Trace() |
| 1128 : cp_offset_(0), | 1144 : cp_offset_(0), |
| 1129 actions_(NULL), | 1145 actions_(NULL), |
| 1130 backtrack_(NULL), | 1146 backtrack_(NULL), |
| 1131 stop_node_(NULL), | 1147 stop_node_(NULL), |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } | 1198 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } |
| 1183 void set_quick_check_performed(QuickCheckDetails* d) { | 1199 void set_quick_check_performed(QuickCheckDetails* d) { |
| 1184 quick_check_performed_ = *d; | 1200 quick_check_performed_ = *d; |
| 1185 } | 1201 } |
| 1186 void InvalidateCurrentCharacter(); | 1202 void InvalidateCurrentCharacter(); |
| 1187 void AdvanceCurrentPositionInTrace(int by, bool ascii); | 1203 void AdvanceCurrentPositionInTrace(int by, bool ascii); |
| 1188 private: | 1204 private: |
| 1189 int FindAffectedRegisters(OutSet* affected_registers); | 1205 int FindAffectedRegisters(OutSet* affected_registers); |
| 1190 void PerformDeferredActions(RegExpMacroAssembler* macro, | 1206 void PerformDeferredActions(RegExpMacroAssembler* macro, |
| 1191 int max_register, | 1207 int max_register, |
| 1192 OutSet& affected_registers); | 1208 OutSet& affected_registers, |
| 1209 OutSet* registers_to_pop, |
| 1210 OutSet* registers_to_clear); |
| 1193 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, | 1211 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, |
| 1194 int max_register, | 1212 int max_register, |
| 1195 OutSet& affected_registers); | 1213 OutSet& registers_to_pop, |
| 1196 void PushAffectedRegisters(RegExpMacroAssembler* macro, | 1214 OutSet& registers_to_clear); |
| 1197 int max_register, | |
| 1198 OutSet& affected_registers); | |
| 1199 int cp_offset_; | 1215 int cp_offset_; |
| 1200 DeferredAction* actions_; | 1216 DeferredAction* actions_; |
| 1201 Label* backtrack_; | 1217 Label* backtrack_; |
| 1202 RegExpNode* stop_node_; | 1218 RegExpNode* stop_node_; |
| 1203 Label* loop_label_; | 1219 Label* loop_label_; |
| 1204 int characters_preloaded_; | 1220 int characters_preloaded_; |
| 1205 int bound_checked_up_to_; | 1221 int bound_checked_up_to_; |
| 1206 QuickCheckDetails quick_check_performed_; | 1222 QuickCheckDetails quick_check_performed_; |
| 1207 }; | 1223 }; |
| 1208 | 1224 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1303 Handle<String> pattern, | 1319 Handle<String> pattern, |
| 1304 bool is_ascii); | 1320 bool is_ascii); |
| 1305 | 1321 |
| 1306 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); | 1322 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); |
| 1307 }; | 1323 }; |
| 1308 | 1324 |
| 1309 | 1325 |
| 1310 } } // namespace v8::internal | 1326 } } // namespace v8::internal |
| 1311 | 1327 |
| 1312 #endif // V8_JSREGEXP_H_ | 1328 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |