| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_JSREGEXP_H_ | 5 #ifndef V8_JSREGEXP_H_ |
| 6 #define V8_JSREGEXP_H_ | 6 #define V8_JSREGEXP_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/assembler.h" | 9 #include "src/assembler.h" |
| 10 #include "src/zone-inl.h" | 10 #include "src/zone-inl.h" |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 TextElement(TextType text_type, RegExpTree* tree) | 438 TextElement(TextType text_type, RegExpTree* tree) |
| 439 : cp_offset_(-1), text_type_(text_type), tree_(tree) {} | 439 : cp_offset_(-1), text_type_(text_type), tree_(tree) {} |
| 440 | 440 |
| 441 int cp_offset_; | 441 int cp_offset_; |
| 442 TextType text_type_; | 442 TextType text_type_; |
| 443 RegExpTree* tree_; | 443 RegExpTree* tree_; |
| 444 }; | 444 }; |
| 445 | 445 |
| 446 | 446 |
| 447 class Trace; | 447 class Trace; |
| 448 | 448 struct PreloadState; |
| 449 class GreedyLoopState; |
| 450 class AlternativeGenerationList; |
| 449 | 451 |
| 450 struct NodeInfo { | 452 struct NodeInfo { |
| 451 NodeInfo() | 453 NodeInfo() |
| 452 : being_analyzed(false), | 454 : being_analyzed(false), |
| 453 been_analyzed(false), | 455 been_analyzed(false), |
| 454 follows_word_interest(false), | 456 follows_word_interest(false), |
| 455 follows_newline_interest(false), | 457 follows_newline_interest(false), |
| 456 follows_start_interest(false), | 458 follows_start_interest(false), |
| 457 at_end(false), | 459 at_end(false), |
| 458 visited(false), | 460 visited(false), |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 bool not_at_start); | 1071 bool not_at_start); |
| 1070 virtual void FillInBMInfo(int offset, | 1072 virtual void FillInBMInfo(int offset, |
| 1071 int budget, | 1073 int budget, |
| 1072 BoyerMooreLookahead* bm, | 1074 BoyerMooreLookahead* bm, |
| 1073 bool not_at_start); | 1075 bool not_at_start); |
| 1074 | 1076 |
| 1075 bool being_calculated() { return being_calculated_; } | 1077 bool being_calculated() { return being_calculated_; } |
| 1076 bool not_at_start() { return not_at_start_; } | 1078 bool not_at_start() { return not_at_start_; } |
| 1077 void set_not_at_start() { not_at_start_ = true; } | 1079 void set_not_at_start() { not_at_start_ = true; } |
| 1078 void set_being_calculated(bool b) { being_calculated_ = b; } | 1080 void set_being_calculated(bool b) { being_calculated_ = b; } |
| 1079 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } | 1081 virtual bool try_to_emit_quick_check_for_alternative(bool is_first) { |
| 1082 return true; |
| 1083 } |
| 1080 virtual RegExpNode* FilterASCII(int depth, bool ignore_case); | 1084 virtual RegExpNode* FilterASCII(int depth, bool ignore_case); |
| 1081 | 1085 |
| 1082 protected: | 1086 protected: |
| 1083 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); | 1087 int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); |
| 1084 ZoneList<GuardedAlternative>* alternatives_; | 1088 ZoneList<GuardedAlternative>* alternatives_; |
| 1085 | 1089 |
| 1086 private: | 1090 private: |
| 1087 friend class DispatchTableConstructor; | 1091 friend class DispatchTableConstructor; |
| 1088 friend class Analysis; | 1092 friend class Analysis; |
| 1089 void GenerateGuard(RegExpMacroAssembler* macro_assembler, | 1093 void GenerateGuard(RegExpMacroAssembler* macro_assembler, |
| 1090 Guard* guard, | 1094 Guard* guard, |
| 1091 Trace* trace); | 1095 Trace* trace); |
| 1092 int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least); | 1096 int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_least); |
| 1093 void EmitOutOfLineContinuation(RegExpCompiler* compiler, | 1097 void EmitOutOfLineContinuation(RegExpCompiler* compiler, |
| 1094 Trace* trace, | 1098 Trace* trace, |
| 1095 GuardedAlternative alternative, | 1099 GuardedAlternative alternative, |
| 1096 AlternativeGeneration* alt_gen, | 1100 AlternativeGeneration* alt_gen, |
| 1097 int preload_characters, | 1101 int preload_characters, |
| 1098 bool next_expects_preload); | 1102 bool next_expects_preload); |
| 1103 void SetUpPreLoad(RegExpCompiler* compiler, |
| 1104 Trace* current_trace, |
| 1105 PreloadState* preloads); |
| 1106 void AssertGuardsMentionRegisters(Trace* trace); |
| 1107 int EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler, Trace* trace); |
| 1108 Trace* EmitGreedyLoop(RegExpCompiler* compiler, |
| 1109 Trace* trace, |
| 1110 AlternativeGenerationList* alt_gens, |
| 1111 PreloadState* preloads, |
| 1112 GreedyLoopState* greedy_loop_state, |
| 1113 int text_length); |
| 1114 void EmitChoices(RegExpCompiler* compiler, |
| 1115 AlternativeGenerationList* alt_gens, |
| 1116 int first_choice, |
| 1117 Trace* trace, |
| 1118 bool is_greedy_loop, |
| 1119 PreloadState* preloads); |
| 1099 DispatchTable* table_; | 1120 DispatchTable* table_; |
| 1100 // If true, this node is never checked at the start of the input. | 1121 // 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. | 1122 // Allows a new trace to start with at_start() set to false. |
| 1102 bool not_at_start_; | 1123 bool not_at_start_; |
| 1103 bool being_calculated_; | 1124 bool being_calculated_; |
| 1104 }; | 1125 }; |
| 1105 | 1126 |
| 1106 | 1127 |
| 1107 class NegativeLookaheadChoiceNode: public ChoiceNode { | 1128 class NegativeLookaheadChoiceNode: public ChoiceNode { |
| 1108 public: | 1129 public: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1124 bool not_at_start) { | 1145 bool not_at_start) { |
| 1125 alternatives_->at(1).node()->FillInBMInfo( | 1146 alternatives_->at(1).node()->FillInBMInfo( |
| 1126 offset, budget - 1, bm, not_at_start); | 1147 offset, budget - 1, bm, not_at_start); |
| 1127 if (offset == 0) set_bm_info(not_at_start, bm); | 1148 if (offset == 0) set_bm_info(not_at_start, bm); |
| 1128 } | 1149 } |
| 1129 // For a negative lookahead we don't emit the quick check for the | 1150 // For a negative lookahead we don't emit the quick check for the |
| 1130 // alternative that is expected to fail. This is because quick check code | 1151 // alternative that is expected to fail. This is because quick check code |
| 1131 // starts by loading enough characters for the alternative that takes fewest | 1152 // starts by loading enough characters for the alternative that takes fewest |
| 1132 // characters, but on a negative lookahead the negative branch did not take | 1153 // characters, but on a negative lookahead the negative branch did not take |
| 1133 // part in that calculation (EatsAtLeast) so the assumptions don't hold. | 1154 // part in that calculation (EatsAtLeast) so the assumptions don't hold. |
| 1134 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } | 1155 virtual bool try_to_emit_quick_check_for_alternative(bool is_first) { |
| 1156 return !is_first; |
| 1157 } |
| 1135 virtual RegExpNode* FilterASCII(int depth, bool ignore_case); | 1158 virtual RegExpNode* FilterASCII(int depth, bool ignore_case); |
| 1136 }; | 1159 }; |
| 1137 | 1160 |
| 1138 | 1161 |
| 1139 class LoopChoiceNode: public ChoiceNode { | 1162 class LoopChoiceNode: public ChoiceNode { |
| 1140 public: | 1163 public: |
| 1141 explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone) | 1164 explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone) |
| 1142 : ChoiceNode(2, zone), | 1165 : ChoiceNode(2, zone), |
| 1143 loop_node_(NULL), | 1166 loop_node_(NULL), |
| 1144 continue_node_(NULL), | 1167 continue_node_(NULL), |
| 1145 body_can_be_zero_length_(body_can_be_zero_length) { } | 1168 body_can_be_zero_length_(body_can_be_zero_length) |
| 1169 { } |
| 1146 void AddLoopAlternative(GuardedAlternative alt); | 1170 void AddLoopAlternative(GuardedAlternative alt); |
| 1147 void AddContinueAlternative(GuardedAlternative alt); | 1171 void AddContinueAlternative(GuardedAlternative alt); |
| 1148 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1172 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 1149 virtual int EatsAtLeast(int still_to_find, int budget, bool not_at_start); | 1173 virtual int EatsAtLeast(int still_to_find, int budget, bool not_at_start); |
| 1150 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1174 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1151 RegExpCompiler* compiler, | 1175 RegExpCompiler* compiler, |
| 1152 int characters_filled_in, | 1176 int characters_filled_in, |
| 1153 bool not_at_start); | 1177 bool not_at_start); |
| 1154 virtual void FillInBMInfo(int offset, | 1178 virtual void FillInBMInfo(int offset, |
| 1155 int budget, | 1179 int budget, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 } | 1310 } |
| 1287 } | 1311 } |
| 1288 | 1312 |
| 1289 void SetAll(int map_number) { | 1313 void SetAll(int map_number) { |
| 1290 bitmaps_->at(map_number)->SetAll(); | 1314 bitmaps_->at(map_number)->SetAll(); |
| 1291 } | 1315 } |
| 1292 | 1316 |
| 1293 void SetRest(int from_map) { | 1317 void SetRest(int from_map) { |
| 1294 for (int i = from_map; i < length_; i++) SetAll(i); | 1318 for (int i = from_map; i < length_; i++) SetAll(i); |
| 1295 } | 1319 } |
| 1296 bool EmitSkipInstructions(RegExpMacroAssembler* masm); | 1320 void EmitSkipInstructions(RegExpMacroAssembler* masm); |
| 1297 | 1321 |
| 1298 private: | 1322 private: |
| 1299 // This is the value obtained by EatsAtLeast. If we do not have at least this | 1323 // This is the value obtained by EatsAtLeast. If we do not have at least this |
| 1300 // many characters left in the sample string then the match is bound to fail. | 1324 // many characters left in the sample string then the match is bound to fail. |
| 1301 // Therefore it is OK to read a character this far ahead of the current match | 1325 // Therefore it is OK to read a character this far ahead of the current match |
| 1302 // point. | 1326 // point. |
| 1303 int length_; | 1327 int length_; |
| 1304 RegExpCompiler* compiler_; | 1328 RegExpCompiler* compiler_; |
| 1305 // 0x7f for ASCII, 0xffff for UTF-16. | 1329 // 0x7f for ASCII, 0xffff for UTF-16. |
| 1306 int max_char_; | 1330 int max_char_; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 RegExpNode* stop_node_; | 1503 RegExpNode* stop_node_; |
| 1480 Label* loop_label_; | 1504 Label* loop_label_; |
| 1481 int characters_preloaded_; | 1505 int characters_preloaded_; |
| 1482 int bound_checked_up_to_; | 1506 int bound_checked_up_to_; |
| 1483 QuickCheckDetails quick_check_performed_; | 1507 QuickCheckDetails quick_check_performed_; |
| 1484 int flush_budget_; | 1508 int flush_budget_; |
| 1485 TriBool at_start_; | 1509 TriBool at_start_; |
| 1486 }; | 1510 }; |
| 1487 | 1511 |
| 1488 | 1512 |
| 1513 class GreedyLoopState { |
| 1514 public: |
| 1515 explicit GreedyLoopState(bool not_at_start); |
| 1516 |
| 1517 Label* label() { return &label_; } |
| 1518 Trace* counter_backtrack_trace() { return &counter_backtrack_trace_; } |
| 1519 |
| 1520 private: |
| 1521 Label label_; |
| 1522 Trace counter_backtrack_trace_; |
| 1523 }; |
| 1524 |
| 1525 |
| 1526 struct PreloadState { |
| 1527 static const int kEatsAtLeastNotYetInitialized = -1; |
| 1528 bool preload_is_current_; |
| 1529 bool preload_has_checked_bounds_; |
| 1530 int preload_characters_; |
| 1531 int eats_at_least_; |
| 1532 void init() { |
| 1533 eats_at_least_ = kEatsAtLeastNotYetInitialized; |
| 1534 } |
| 1535 }; |
| 1536 |
| 1537 |
| 1489 class NodeVisitor { | 1538 class NodeVisitor { |
| 1490 public: | 1539 public: |
| 1491 virtual ~NodeVisitor() { } | 1540 virtual ~NodeVisitor() { } |
| 1492 #define DECLARE_VISIT(Type) \ | 1541 #define DECLARE_VISIT(Type) \ |
| 1493 virtual void Visit##Type(Type##Node* that) = 0; | 1542 virtual void Visit##Type(Type##Node* that) = 0; |
| 1494 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1543 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 1495 #undef DECLARE_VISIT | 1544 #undef DECLARE_VISIT |
| 1496 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } | 1545 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } |
| 1497 }; | 1546 }; |
| 1498 | 1547 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 Handle<String> sample_subject, | 1665 Handle<String> sample_subject, |
| 1617 bool is_ascii, Zone* zone); | 1666 bool is_ascii, Zone* zone); |
| 1618 | 1667 |
| 1619 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); | 1668 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); |
| 1620 }; | 1669 }; |
| 1621 | 1670 |
| 1622 | 1671 |
| 1623 } } // namespace v8::internal | 1672 } } // namespace v8::internal |
| 1624 | 1673 |
| 1625 #endif // V8_JSREGEXP_H_ | 1674 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |