OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_REGEXP_H_ | 5 #ifndef RUNTIME_VM_REGEXP_H_ |
6 #define RUNTIME_VM_REGEXP_H_ | 6 #define RUNTIME_VM_REGEXP_H_ |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/flow_graph_compiler.h" |
9 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
10 #include "vm/flow_graph_compiler.h" | |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/regexp_assembler.h" | 12 #include "vm/regexp_assembler.h" |
13 | 13 |
14 namespace dart { | 14 namespace dart { |
15 | 15 |
16 class NodeVisitor; | 16 class NodeVisitor; |
17 class RegExpCompiler; | 17 class RegExpCompiler; |
18 class RegExpMacroAssembler; | 18 class RegExpMacroAssembler; |
19 class RegExpNode; | 19 class RegExpNode; |
20 class RegExpTree; | 20 class RegExpTree; |
21 class BoyerMooreLookahead; | 21 class BoyerMooreLookahead; |
22 | 22 |
23 | |
24 // Represents code units in the range from from_ to to_, both ends are | 23 // Represents code units in the range from from_ to to_, both ends are |
25 // inclusive. | 24 // inclusive. |
26 class CharacterRange { | 25 class CharacterRange { |
27 public: | 26 public: |
28 CharacterRange() : from_(0), to_(0) {} | 27 CharacterRange() : from_(0), to_(0) {} |
29 CharacterRange(uint16_t from, uint16_t to) : from_(from), to_(to) {} | 28 CharacterRange(uint16_t from, uint16_t to) : from_(from), to_(to) {} |
30 | 29 |
31 static void AddClassEscape(uint16_t type, | 30 static void AddClassEscape(uint16_t type, |
32 ZoneGrowableArray<CharacterRange>* ranges); | 31 ZoneGrowableArray<CharacterRange>* ranges); |
33 static GrowableArray<const intptr_t> GetWordBounds(); | 32 static GrowableArray<const intptr_t> GetWordBounds(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 static const intptr_t kStartMarker = (1 << 24); | 70 static const intptr_t kStartMarker = (1 << 24); |
72 static const intptr_t kPayloadMask = (1 << 24) - 1; | 71 static const intptr_t kPayloadMask = (1 << 24) - 1; |
73 | 72 |
74 private: | 73 private: |
75 uint16_t from_; | 74 uint16_t from_; |
76 uint16_t to_; | 75 uint16_t to_; |
77 | 76 |
78 DISALLOW_ALLOCATION(); | 77 DISALLOW_ALLOCATION(); |
79 }; | 78 }; |
80 | 79 |
81 | |
82 // A set of unsigned integers that behaves especially well on small | 80 // A set of unsigned integers that behaves especially well on small |
83 // integers (< 32). May do zone-allocation. | 81 // integers (< 32). May do zone-allocation. |
84 class OutSet : public ZoneAllocated { | 82 class OutSet : public ZoneAllocated { |
85 public: | 83 public: |
86 OutSet() : first_(0), remaining_(NULL), successors_(NULL) {} | 84 OutSet() : first_(0), remaining_(NULL), successors_(NULL) {} |
87 OutSet* Extend(unsigned value, Zone* zone); | 85 OutSet* Extend(unsigned value, Zone* zone); |
88 bool Get(unsigned value) const; | 86 bool Get(unsigned value) const; |
89 static const unsigned kFirstLimit = 32; | 87 static const unsigned kFirstLimit = 32; |
90 | 88 |
91 private: | 89 private: |
92 // Destructively set a value in this set. In most cases you want | 90 // Destructively set a value in this set. In most cases you want |
93 // to use Extend instead to ensure that only one instance exists | 91 // to use Extend instead to ensure that only one instance exists |
94 // that contains the same values. | 92 // that contains the same values. |
95 void Set(unsigned value, Zone* zone); | 93 void Set(unsigned value, Zone* zone); |
96 | 94 |
97 // The successors are a list of sets that contain the same values | 95 // The successors are a list of sets that contain the same values |
98 // as this set and the one more value that is not present in this | 96 // as this set and the one more value that is not present in this |
99 // set. | 97 // set. |
100 ZoneGrowableArray<OutSet*>* successors() { return successors_; } | 98 ZoneGrowableArray<OutSet*>* successors() { return successors_; } |
101 | 99 |
102 OutSet(uint32_t first, ZoneGrowableArray<unsigned>* remaining) | 100 OutSet(uint32_t first, ZoneGrowableArray<unsigned>* remaining) |
103 : first_(first), remaining_(remaining), successors_(NULL) {} | 101 : first_(first), remaining_(remaining), successors_(NULL) {} |
104 uint32_t first_; | 102 uint32_t first_; |
105 ZoneGrowableArray<unsigned>* remaining_; | 103 ZoneGrowableArray<unsigned>* remaining_; |
106 ZoneGrowableArray<OutSet*>* successors_; | 104 ZoneGrowableArray<OutSet*>* successors_; |
107 friend class Trace; | 105 friend class Trace; |
108 }; | 106 }; |
109 | 107 |
110 | |
111 #define FOR_EACH_NODE_TYPE(VISIT) \ | 108 #define FOR_EACH_NODE_TYPE(VISIT) \ |
112 VISIT(End) \ | 109 VISIT(End) \ |
113 VISIT(Action) \ | 110 VISIT(Action) \ |
114 VISIT(Choice) \ | 111 VISIT(Choice) \ |
115 VISIT(BackReference) \ | 112 VISIT(BackReference) \ |
116 VISIT(Assertion) \ | 113 VISIT(Assertion) \ |
117 VISIT(Text) | 114 VISIT(Text) |
118 | 115 |
119 | |
120 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ | 116 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ |
121 VISIT(Disjunction) \ | 117 VISIT(Disjunction) \ |
122 VISIT(Alternative) \ | 118 VISIT(Alternative) \ |
123 VISIT(Assertion) \ | 119 VISIT(Assertion) \ |
124 VISIT(CharacterClass) \ | 120 VISIT(CharacterClass) \ |
125 VISIT(Atom) \ | 121 VISIT(Atom) \ |
126 VISIT(Quantifier) \ | 122 VISIT(Quantifier) \ |
127 VISIT(Capture) \ | 123 VISIT(Capture) \ |
128 VISIT(Lookahead) \ | 124 VISIT(Lookahead) \ |
129 VISIT(BackReference) \ | 125 VISIT(BackReference) \ |
130 VISIT(Empty) \ | 126 VISIT(Empty) \ |
131 VISIT(Text) | 127 VISIT(Text) |
132 | 128 |
133 | |
134 #define FORWARD_DECLARE(Name) class RegExp##Name; | 129 #define FORWARD_DECLARE(Name) class RegExp##Name; |
135 FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE) | 130 FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE) |
136 #undef FORWARD_DECLARE | 131 #undef FORWARD_DECLARE |
137 | 132 |
138 | |
139 class TextElement { | 133 class TextElement { |
140 public: | 134 public: |
141 enum TextType { ATOM, CHAR_CLASS }; | 135 enum TextType { ATOM, CHAR_CLASS }; |
142 | 136 |
143 static TextElement Atom(RegExpAtom* atom); | 137 static TextElement Atom(RegExpAtom* atom); |
144 static TextElement CharClass(RegExpCharacterClass* char_class); | 138 static TextElement CharClass(RegExpCharacterClass* char_class); |
145 | 139 |
146 intptr_t cp_offset() const { return cp_offset_; } | 140 intptr_t cp_offset() const { return cp_offset_; } |
147 void set_cp_offset(intptr_t cp_offset) { cp_offset_ = cp_offset; } | 141 void set_cp_offset(intptr_t cp_offset) { cp_offset_ = cp_offset; } |
148 intptr_t length() const; | 142 intptr_t length() const; |
(...skipping 16 matching lines...) Expand all Loading... |
165 TextElement(TextType text_type, RegExpTree* tree) | 159 TextElement(TextType text_type, RegExpTree* tree) |
166 : cp_offset_(-1), text_type_(text_type), tree_(tree) {} | 160 : cp_offset_(-1), text_type_(text_type), tree_(tree) {} |
167 | 161 |
168 intptr_t cp_offset_; | 162 intptr_t cp_offset_; |
169 TextType text_type_; | 163 TextType text_type_; |
170 RegExpTree* tree_; | 164 RegExpTree* tree_; |
171 | 165 |
172 DISALLOW_ALLOCATION(); | 166 DISALLOW_ALLOCATION(); |
173 }; | 167 }; |
174 | 168 |
175 | |
176 class Trace; | 169 class Trace; |
177 struct PreloadState; | 170 struct PreloadState; |
178 class GreedyLoopState; | 171 class GreedyLoopState; |
179 class AlternativeGenerationList; | 172 class AlternativeGenerationList; |
180 | 173 |
181 struct NodeInfo { | 174 struct NodeInfo { |
182 NodeInfo() | 175 NodeInfo() |
183 : being_analyzed(false), | 176 : being_analyzed(false), |
184 been_analyzed(false), | 177 been_analyzed(false), |
185 follows_word_interest(false), | 178 follows_word_interest(false), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 // character was. | 225 // character was. |
233 bool follows_word_interest : 1; | 226 bool follows_word_interest : 1; |
234 bool follows_newline_interest : 1; | 227 bool follows_newline_interest : 1; |
235 bool follows_start_interest : 1; | 228 bool follows_start_interest : 1; |
236 | 229 |
237 bool at_end : 1; | 230 bool at_end : 1; |
238 bool visited : 1; | 231 bool visited : 1; |
239 bool replacement_calculated : 1; | 232 bool replacement_calculated : 1; |
240 }; | 233 }; |
241 | 234 |
242 | |
243 // Details of a quick mask-compare check that can look ahead in the | 235 // Details of a quick mask-compare check that can look ahead in the |
244 // input stream. | 236 // input stream. |
245 class QuickCheckDetails { | 237 class QuickCheckDetails { |
246 public: | 238 public: |
247 QuickCheckDetails() | 239 QuickCheckDetails() |
248 : characters_(0), mask_(0), value_(0), cannot_match_(false) {} | 240 : characters_(0), mask_(0), value_(0), cannot_match_(false) {} |
249 explicit QuickCheckDetails(intptr_t characters) | 241 explicit QuickCheckDetails(intptr_t characters) |
250 : characters_(characters), mask_(0), value_(0), cannot_match_(false) {} | 242 : characters_(characters), mask_(0), value_(0), cannot_match_(false) {} |
251 bool Rationalize(bool one_byte); | 243 bool Rationalize(bool one_byte); |
252 // Merge in the information from another branch of an alternation. | 244 // Merge in the information from another branch of an alternation. |
(...skipping 27 matching lines...) Expand all Loading... |
280 // These values are the condensate of the above array after Rationalize(). | 272 // These values are the condensate of the above array after Rationalize(). |
281 uint32_t mask_; | 273 uint32_t mask_; |
282 uint32_t value_; | 274 uint32_t value_; |
283 // If set to true, there is no way this quick check can match at all. | 275 // If set to true, there is no way this quick check can match at all. |
284 // E.g., if it requires to be at the start of the input, and isn't. | 276 // E.g., if it requires to be at the start of the input, and isn't. |
285 bool cannot_match_; | 277 bool cannot_match_; |
286 | 278 |
287 DISALLOW_ALLOCATION(); | 279 DISALLOW_ALLOCATION(); |
288 }; | 280 }; |
289 | 281 |
290 | |
291 class RegExpNode : public ZoneAllocated { | 282 class RegExpNode : public ZoneAllocated { |
292 public: | 283 public: |
293 explicit RegExpNode(Zone* zone) | 284 explicit RegExpNode(Zone* zone) |
294 : replacement_(NULL), trace_count_(0), zone_(zone) { | 285 : replacement_(NULL), trace_count_(0), zone_(zone) { |
295 bm_info_[0] = bm_info_[1] = NULL; | 286 bm_info_[0] = bm_info_[1] = NULL; |
296 } | 287 } |
297 virtual ~RegExpNode(); | 288 virtual ~RegExpNode(); |
298 virtual void Accept(NodeVisitor* visitor) = 0; | 289 virtual void Accept(NodeVisitor* visitor) = 0; |
299 // Generates a goto to this node or actually generates the code at this point. | 290 // Generates a goto to this node or actually generates the code at this point. |
300 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; | 291 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 // This variable keeps track of how many times code has been generated for | 399 // This variable keeps track of how many times code has been generated for |
409 // this node (in different traces). We don't keep track of where the | 400 // this node (in different traces). We don't keep track of where the |
410 // generated code is located unless the code is generated at the start of | 401 // generated code is located unless the code is generated at the start of |
411 // a trace, in which case it is generic and can be reused by flushing the | 402 // a trace, in which case it is generic and can be reused by flushing the |
412 // deferred operations in the current trace and generating a goto. | 403 // deferred operations in the current trace and generating a goto. |
413 intptr_t trace_count_; | 404 intptr_t trace_count_; |
414 BoyerMooreLookahead* bm_info_[2]; | 405 BoyerMooreLookahead* bm_info_[2]; |
415 Zone* zone_; | 406 Zone* zone_; |
416 }; | 407 }; |
417 | 408 |
418 | |
419 // A simple closed interval. | 409 // A simple closed interval. |
420 class Interval { | 410 class Interval { |
421 public: | 411 public: |
422 Interval() : from_(kNone), to_(kNone) {} | 412 Interval() : from_(kNone), to_(kNone) {} |
423 Interval(intptr_t from, intptr_t to) : from_(from), to_(to) {} | 413 Interval(intptr_t from, intptr_t to) : from_(from), to_(to) {} |
424 | 414 |
425 Interval Union(Interval that) { | 415 Interval Union(Interval that) { |
426 if (that.from_ == kNone) | 416 if (that.from_ == kNone) |
427 return *this; | 417 return *this; |
428 else if (from_ == kNone) | 418 else if (from_ == kNone) |
(...skipping 11 matching lines...) Expand all Loading... |
440 static Interval Empty() { return Interval(); } | 430 static Interval Empty() { return Interval(); } |
441 static const intptr_t kNone = -1; | 431 static const intptr_t kNone = -1; |
442 | 432 |
443 private: | 433 private: |
444 intptr_t from_; | 434 intptr_t from_; |
445 intptr_t to_; | 435 intptr_t to_; |
446 | 436 |
447 DISALLOW_ALLOCATION(); | 437 DISALLOW_ALLOCATION(); |
448 }; | 438 }; |
449 | 439 |
450 | |
451 class SeqRegExpNode : public RegExpNode { | 440 class SeqRegExpNode : public RegExpNode { |
452 public: | 441 public: |
453 explicit SeqRegExpNode(RegExpNode* on_success) | 442 explicit SeqRegExpNode(RegExpNode* on_success) |
454 : RegExpNode(on_success->zone()), on_success_(on_success) {} | 443 : RegExpNode(on_success->zone()), on_success_(on_success) {} |
455 RegExpNode* on_success() { return on_success_; } | 444 RegExpNode* on_success() { return on_success_; } |
456 void set_on_success(RegExpNode* node) { on_success_ = node; } | 445 void set_on_success(RegExpNode* node) { on_success_ = node; } |
457 virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case); | 446 virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case); |
458 virtual void FillInBMInfo(intptr_t offset, | 447 virtual void FillInBMInfo(intptr_t offset, |
459 intptr_t budget, | 448 intptr_t budget, |
460 BoyerMooreLookahead* bm, | 449 BoyerMooreLookahead* bm, |
461 bool not_at_start) { | 450 bool not_at_start) { |
462 on_success_->FillInBMInfo(offset, budget - 1, bm, not_at_start); | 451 on_success_->FillInBMInfo(offset, budget - 1, bm, not_at_start); |
463 if (offset == 0) set_bm_info(not_at_start, bm); | 452 if (offset == 0) set_bm_info(not_at_start, bm); |
464 } | 453 } |
465 | 454 |
466 protected: | 455 protected: |
467 RegExpNode* FilterSuccessor(intptr_t depth, bool ignore_case); | 456 RegExpNode* FilterSuccessor(intptr_t depth, bool ignore_case); |
468 | 457 |
469 private: | 458 private: |
470 RegExpNode* on_success_; | 459 RegExpNode* on_success_; |
471 }; | 460 }; |
472 | 461 |
473 | |
474 class ActionNode : public SeqRegExpNode { | 462 class ActionNode : public SeqRegExpNode { |
475 public: | 463 public: |
476 enum ActionType { | 464 enum ActionType { |
477 SET_REGISTER, | 465 SET_REGISTER, |
478 INCREMENT_REGISTER, | 466 INCREMENT_REGISTER, |
479 STORE_POSITION, | 467 STORE_POSITION, |
480 BEGIN_SUBMATCH, | 468 BEGIN_SUBMATCH, |
481 POSITIVE_SUBMATCH_SUCCESS, | 469 POSITIVE_SUBMATCH_SUCCESS, |
482 EMPTY_MATCH_CHECK, | 470 EMPTY_MATCH_CHECK, |
483 CLEAR_CAPTURES | 471 CLEAR_CAPTURES |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 intptr_t range_from; | 540 intptr_t range_from; |
553 intptr_t range_to; | 541 intptr_t range_to; |
554 } u_clear_captures; | 542 } u_clear_captures; |
555 } data_; | 543 } data_; |
556 ActionNode(ActionType action_type, RegExpNode* on_success) | 544 ActionNode(ActionType action_type, RegExpNode* on_success) |
557 : SeqRegExpNode(on_success), action_type_(action_type) {} | 545 : SeqRegExpNode(on_success), action_type_(action_type) {} |
558 ActionType action_type_; | 546 ActionType action_type_; |
559 friend class DotPrinter; | 547 friend class DotPrinter; |
560 }; | 548 }; |
561 | 549 |
562 | |
563 class TextNode : public SeqRegExpNode { | 550 class TextNode : public SeqRegExpNode { |
564 public: | 551 public: |
565 TextNode(ZoneGrowableArray<TextElement>* elms, RegExpNode* on_success) | 552 TextNode(ZoneGrowableArray<TextElement>* elms, RegExpNode* on_success) |
566 : SeqRegExpNode(on_success), elms_(elms) {} | 553 : SeqRegExpNode(on_success), elms_(elms) {} |
567 TextNode(RegExpCharacterClass* that, RegExpNode* on_success) | 554 TextNode(RegExpCharacterClass* that, RegExpNode* on_success) |
568 : SeqRegExpNode(on_success), | 555 : SeqRegExpNode(on_success), |
569 elms_(new (zone()) ZoneGrowableArray<TextElement>(1)) { | 556 elms_(new (zone()) ZoneGrowableArray<TextElement>(1)) { |
570 elms_->Add(TextElement::CharClass(that)); | 557 elms_->Add(TextElement::CharClass(that)); |
571 } | 558 } |
572 virtual void Accept(NodeVisitor* visitor); | 559 virtual void Accept(NodeVisitor* visitor); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 void TextEmitPass(RegExpCompiler* compiler, | 591 void TextEmitPass(RegExpCompiler* compiler, |
605 TextEmitPassType pass, | 592 TextEmitPassType pass, |
606 bool preloaded, | 593 bool preloaded, |
607 Trace* trace, | 594 Trace* trace, |
608 bool first_element_checked, | 595 bool first_element_checked, |
609 intptr_t* checked_up_to); | 596 intptr_t* checked_up_to); |
610 intptr_t Length(); | 597 intptr_t Length(); |
611 ZoneGrowableArray<TextElement>* elms_; | 598 ZoneGrowableArray<TextElement>* elms_; |
612 }; | 599 }; |
613 | 600 |
614 | |
615 class AssertionNode : public SeqRegExpNode { | 601 class AssertionNode : public SeqRegExpNode { |
616 public: | 602 public: |
617 enum AssertionType { | 603 enum AssertionType { |
618 AT_END, | 604 AT_END, |
619 AT_START, | 605 AT_START, |
620 AT_BOUNDARY, | 606 AT_BOUNDARY, |
621 AT_NON_BOUNDARY, | 607 AT_NON_BOUNDARY, |
622 AFTER_NEWLINE | 608 AFTER_NEWLINE |
623 }; | 609 }; |
624 static AssertionNode* AtEnd(RegExpNode* on_success) { | 610 static AssertionNode* AtEnd(RegExpNode* on_success) { |
(...skipping 30 matching lines...) Expand all Loading... |
655 void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace); | 641 void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace); |
656 enum IfPrevious { kIsNonWord, kIsWord }; | 642 enum IfPrevious { kIsNonWord, kIsWord }; |
657 void BacktrackIfPrevious(RegExpCompiler* compiler, | 643 void BacktrackIfPrevious(RegExpCompiler* compiler, |
658 Trace* trace, | 644 Trace* trace, |
659 IfPrevious backtrack_if_previous); | 645 IfPrevious backtrack_if_previous); |
660 AssertionNode(AssertionType t, RegExpNode* on_success) | 646 AssertionNode(AssertionType t, RegExpNode* on_success) |
661 : SeqRegExpNode(on_success), assertion_type_(t) {} | 647 : SeqRegExpNode(on_success), assertion_type_(t) {} |
662 AssertionType assertion_type_; | 648 AssertionType assertion_type_; |
663 }; | 649 }; |
664 | 650 |
665 | |
666 class BackReferenceNode : public SeqRegExpNode { | 651 class BackReferenceNode : public SeqRegExpNode { |
667 public: | 652 public: |
668 BackReferenceNode(intptr_t start_reg, | 653 BackReferenceNode(intptr_t start_reg, |
669 intptr_t end_reg, | 654 intptr_t end_reg, |
670 RegExpNode* on_success) | 655 RegExpNode* on_success) |
671 : SeqRegExpNode(on_success), start_reg_(start_reg), end_reg_(end_reg) {} | 656 : SeqRegExpNode(on_success), start_reg_(start_reg), end_reg_(end_reg) {} |
672 virtual void Accept(NodeVisitor* visitor); | 657 virtual void Accept(NodeVisitor* visitor); |
673 intptr_t start_register() { return start_reg_; } | 658 intptr_t start_register() { return start_reg_; } |
674 intptr_t end_register() { return end_reg_; } | 659 intptr_t end_register() { return end_reg_; } |
675 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 660 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
676 virtual intptr_t EatsAtLeast(intptr_t still_to_find, | 661 virtual intptr_t EatsAtLeast(intptr_t still_to_find, |
677 intptr_t recursion_depth, | 662 intptr_t recursion_depth, |
678 bool not_at_start); | 663 bool not_at_start); |
679 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 664 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
680 RegExpCompiler* compiler, | 665 RegExpCompiler* compiler, |
681 intptr_t characters_filled_in, | 666 intptr_t characters_filled_in, |
682 bool not_at_start) { | 667 bool not_at_start) { |
683 return; | 668 return; |
684 } | 669 } |
685 virtual void FillInBMInfo(intptr_t offset, | 670 virtual void FillInBMInfo(intptr_t offset, |
686 intptr_t budget, | 671 intptr_t budget, |
687 BoyerMooreLookahead* bm, | 672 BoyerMooreLookahead* bm, |
688 bool not_at_start); | 673 bool not_at_start); |
689 | 674 |
690 private: | 675 private: |
691 intptr_t start_reg_; | 676 intptr_t start_reg_; |
692 intptr_t end_reg_; | 677 intptr_t end_reg_; |
693 }; | 678 }; |
694 | 679 |
695 | |
696 class EndNode : public RegExpNode { | 680 class EndNode : public RegExpNode { |
697 public: | 681 public: |
698 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; | 682 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; |
699 explicit EndNode(Action action, Zone* zone) | 683 explicit EndNode(Action action, Zone* zone) |
700 : RegExpNode(zone), action_(action) {} | 684 : RegExpNode(zone), action_(action) {} |
701 virtual void Accept(NodeVisitor* visitor); | 685 virtual void Accept(NodeVisitor* visitor); |
702 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 686 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
703 virtual intptr_t EatsAtLeast(intptr_t still_to_find, | 687 virtual intptr_t EatsAtLeast(intptr_t still_to_find, |
704 intptr_t recursion_depth, | 688 intptr_t recursion_depth, |
705 bool not_at_start) { | 689 bool not_at_start) { |
(...skipping 11 matching lines...) Expand all Loading... |
717 BoyerMooreLookahead* bm, | 701 BoyerMooreLookahead* bm, |
718 bool not_at_start) { | 702 bool not_at_start) { |
719 // Returning 0 from EatsAtLeast should ensure we never get here. | 703 // Returning 0 from EatsAtLeast should ensure we never get here. |
720 UNREACHABLE(); | 704 UNREACHABLE(); |
721 } | 705 } |
722 | 706 |
723 private: | 707 private: |
724 Action action_; | 708 Action action_; |
725 }; | 709 }; |
726 | 710 |
727 | |
728 class NegativeSubmatchSuccess : public EndNode { | 711 class NegativeSubmatchSuccess : public EndNode { |
729 public: | 712 public: |
730 NegativeSubmatchSuccess(intptr_t stack_pointer_reg, | 713 NegativeSubmatchSuccess(intptr_t stack_pointer_reg, |
731 intptr_t position_reg, | 714 intptr_t position_reg, |
732 intptr_t clear_capture_count, | 715 intptr_t clear_capture_count, |
733 intptr_t clear_capture_start, | 716 intptr_t clear_capture_start, |
734 Zone* zone) | 717 Zone* zone) |
735 : EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone), | 718 : EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone), |
736 stack_pointer_register_(stack_pointer_reg), | 719 stack_pointer_register_(stack_pointer_reg), |
737 current_position_register_(position_reg), | 720 current_position_register_(position_reg), |
738 clear_capture_count_(clear_capture_count), | 721 clear_capture_count_(clear_capture_count), |
739 clear_capture_start_(clear_capture_start) {} | 722 clear_capture_start_(clear_capture_start) {} |
740 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 723 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
741 | 724 |
742 private: | 725 private: |
743 intptr_t stack_pointer_register_; | 726 intptr_t stack_pointer_register_; |
744 intptr_t current_position_register_; | 727 intptr_t current_position_register_; |
745 intptr_t clear_capture_count_; | 728 intptr_t clear_capture_count_; |
746 intptr_t clear_capture_start_; | 729 intptr_t clear_capture_start_; |
747 }; | 730 }; |
748 | 731 |
749 | |
750 class Guard : public ZoneAllocated { | 732 class Guard : public ZoneAllocated { |
751 public: | 733 public: |
752 enum Relation { LT, GEQ }; | 734 enum Relation { LT, GEQ }; |
753 Guard(intptr_t reg, Relation op, intptr_t value) | 735 Guard(intptr_t reg, Relation op, intptr_t value) |
754 : reg_(reg), op_(op), value_(value) {} | 736 : reg_(reg), op_(op), value_(value) {} |
755 intptr_t reg() { return reg_; } | 737 intptr_t reg() { return reg_; } |
756 Relation op() { return op_; } | 738 Relation op() { return op_; } |
757 intptr_t value() { return value_; } | 739 intptr_t value() { return value_; } |
758 | 740 |
759 private: | 741 private: |
760 intptr_t reg_; | 742 intptr_t reg_; |
761 Relation op_; | 743 Relation op_; |
762 intptr_t value_; | 744 intptr_t value_; |
763 }; | 745 }; |
764 | 746 |
765 | |
766 class GuardedAlternative { | 747 class GuardedAlternative { |
767 public: | 748 public: |
768 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) {} | 749 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) {} |
769 void AddGuard(Guard* guard, Zone* zone); | 750 void AddGuard(Guard* guard, Zone* zone); |
770 RegExpNode* node() { return node_; } | 751 RegExpNode* node() { return node_; } |
771 void set_node(RegExpNode* node) { node_ = node; } | 752 void set_node(RegExpNode* node) { node_ = node; } |
772 ZoneGrowableArray<Guard*>* guards() { return guards_; } | 753 ZoneGrowableArray<Guard*>* guards() { return guards_; } |
773 | 754 |
774 private: | 755 private: |
775 RegExpNode* node_; | 756 RegExpNode* node_; |
776 ZoneGrowableArray<Guard*>* guards_; | 757 ZoneGrowableArray<Guard*>* guards_; |
777 | 758 |
778 DISALLOW_ALLOCATION(); | 759 DISALLOW_ALLOCATION(); |
779 }; | 760 }; |
780 | 761 |
781 | |
782 struct AlternativeGeneration; | 762 struct AlternativeGeneration; |
783 | 763 |
784 | |
785 class ChoiceNode : public RegExpNode { | 764 class ChoiceNode : public RegExpNode { |
786 public: | 765 public: |
787 explicit ChoiceNode(intptr_t expected_size, Zone* zone) | 766 explicit ChoiceNode(intptr_t expected_size, Zone* zone) |
788 : RegExpNode(zone), | 767 : RegExpNode(zone), |
789 alternatives_(new (zone) | 768 alternatives_(new (zone) |
790 ZoneGrowableArray<GuardedAlternative>(expected_size)), | 769 ZoneGrowableArray<GuardedAlternative>(expected_size)), |
791 not_at_start_(false), | 770 not_at_start_(false), |
792 being_calculated_(false) {} | 771 being_calculated_(false) {} |
793 virtual void Accept(NodeVisitor* visitor); | 772 virtual void Accept(NodeVisitor* visitor); |
794 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } | 773 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 AlternativeGenerationList* alt_gens, | 833 AlternativeGenerationList* alt_gens, |
855 intptr_t first_choice, | 834 intptr_t first_choice, |
856 Trace* trace, | 835 Trace* trace, |
857 PreloadState* preloads); | 836 PreloadState* preloads); |
858 // If true, this node is never checked at the start of the input. | 837 // If true, this node is never checked at the start of the input. |
859 // Allows a new trace to start with at_start() set to false. | 838 // Allows a new trace to start with at_start() set to false. |
860 bool not_at_start_; | 839 bool not_at_start_; |
861 bool being_calculated_; | 840 bool being_calculated_; |
862 }; | 841 }; |
863 | 842 |
864 | |
865 class NegativeLookaheadChoiceNode : public ChoiceNode { | 843 class NegativeLookaheadChoiceNode : public ChoiceNode { |
866 public: | 844 public: |
867 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, | 845 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, |
868 GuardedAlternative then_do_this, | 846 GuardedAlternative then_do_this, |
869 Zone* zone) | 847 Zone* zone) |
870 : ChoiceNode(2, zone) { | 848 : ChoiceNode(2, zone) { |
871 AddAlternative(this_must_fail); | 849 AddAlternative(this_must_fail); |
872 AddAlternative(then_do_this); | 850 AddAlternative(then_do_this); |
873 } | 851 } |
874 virtual intptr_t EatsAtLeast(intptr_t still_to_find, | 852 virtual intptr_t EatsAtLeast(intptr_t still_to_find, |
(...skipping 15 matching lines...) Expand all Loading... |
890 // alternative that is expected to fail. This is because quick check code | 868 // alternative that is expected to fail. This is because quick check code |
891 // starts by loading enough characters for the alternative that takes fewest | 869 // starts by loading enough characters for the alternative that takes fewest |
892 // characters, but on a negative lookahead the negative branch did not take | 870 // characters, but on a negative lookahead the negative branch did not take |
893 // part in that calculation (EatsAtLeast) so the assumptions don't hold. | 871 // part in that calculation (EatsAtLeast) so the assumptions don't hold. |
894 virtual bool try_to_emit_quick_check_for_alternative(bool is_first) { | 872 virtual bool try_to_emit_quick_check_for_alternative(bool is_first) { |
895 return !is_first; | 873 return !is_first; |
896 } | 874 } |
897 virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case); | 875 virtual RegExpNode* FilterOneByte(intptr_t depth, bool ignore_case); |
898 }; | 876 }; |
899 | 877 |
900 | |
901 class LoopChoiceNode : public ChoiceNode { | 878 class LoopChoiceNode : public ChoiceNode { |
902 public: | 879 public: |
903 explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone) | 880 explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone) |
904 : ChoiceNode(2, zone), | 881 : ChoiceNode(2, zone), |
905 loop_node_(NULL), | 882 loop_node_(NULL), |
906 continue_node_(NULL), | 883 continue_node_(NULL), |
907 body_can_be_zero_length_(body_can_be_zero_length) {} | 884 body_can_be_zero_length_(body_can_be_zero_length) {} |
908 void AddLoopAlternative(GuardedAlternative alt); | 885 void AddLoopAlternative(GuardedAlternative alt); |
909 void AddContinueAlternative(GuardedAlternative alt); | 886 void AddContinueAlternative(GuardedAlternative alt); |
910 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 887 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
(...skipping 20 matching lines...) Expand all Loading... |
931 // goes back to the node itself. | 908 // goes back to the node itself. |
932 void AddAlternative(GuardedAlternative node) { | 909 void AddAlternative(GuardedAlternative node) { |
933 ChoiceNode::AddAlternative(node); | 910 ChoiceNode::AddAlternative(node); |
934 } | 911 } |
935 | 912 |
936 RegExpNode* loop_node_; | 913 RegExpNode* loop_node_; |
937 RegExpNode* continue_node_; | 914 RegExpNode* continue_node_; |
938 bool body_can_be_zero_length_; | 915 bool body_can_be_zero_length_; |
939 }; | 916 }; |
940 | 917 |
941 | |
942 // Improve the speed that we scan for an initial point where a non-anchored | 918 // Improve the speed that we scan for an initial point where a non-anchored |
943 // regexp can match by using a Boyer-Moore-like table. This is done by | 919 // regexp can match by using a Boyer-Moore-like table. This is done by |
944 // identifying non-greedy non-capturing loops in the nodes that eat any | 920 // identifying non-greedy non-capturing loops in the nodes that eat any |
945 // character one at a time. For example in the middle of the regexp | 921 // character one at a time. For example in the middle of the regexp |
946 // /foo[\s\S]*?bar/ we find such a loop. There is also such a loop implicitly | 922 // /foo[\s\S]*?bar/ we find such a loop. There is also such a loop implicitly |
947 // inserted at the start of any non-anchored regexp. | 923 // inserted at the start of any non-anchored regexp. |
948 // | 924 // |
949 // When we have found such a loop we look ahead in the nodes to find the set of | 925 // When we have found such a loop we look ahead in the nodes to find the set of |
950 // characters that can come at given distances. For example for the regexp | 926 // characters that can come at given distances. For example for the regexp |
951 // /.?foo/ we know that there are at least 3 characters ahead of us, and the | 927 // /.?foo/ we know that there are at least 3 characters ahead of us, and the |
(...skipping 12 matching lines...) Expand all Loading... |
964 // We also have another lookahead mechanism (called quick check in the code), | 940 // We also have another lookahead mechanism (called quick check in the code), |
965 // which uses a wide load of multiple characters followed by a mask and compare | 941 // which uses a wide load of multiple characters followed by a mask and compare |
966 // to determine whether a match is possible at this point. | 942 // to determine whether a match is possible at this point. |
967 enum ContainedInLattice { | 943 enum ContainedInLattice { |
968 kNotYet = 0, | 944 kNotYet = 0, |
969 kLatticeIn = 1, | 945 kLatticeIn = 1, |
970 kLatticeOut = 2, | 946 kLatticeOut = 2, |
971 kLatticeUnknown = 3 // Can also mean both in and out. | 947 kLatticeUnknown = 3 // Can also mean both in and out. |
972 }; | 948 }; |
973 | 949 |
974 | |
975 inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b) { | 950 inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b) { |
976 return static_cast<ContainedInLattice>(a | b); | 951 return static_cast<ContainedInLattice>(a | b); |
977 } | 952 } |
978 | 953 |
979 | |
980 ContainedInLattice AddRange(ContainedInLattice a, | 954 ContainedInLattice AddRange(ContainedInLattice a, |
981 const intptr_t* ranges, | 955 const intptr_t* ranges, |
982 intptr_t ranges_size, | 956 intptr_t ranges_size, |
983 Interval new_range); | 957 Interval new_range); |
984 | 958 |
985 | |
986 class BoyerMoorePositionInfo : public ZoneAllocated { | 959 class BoyerMoorePositionInfo : public ZoneAllocated { |
987 public: | 960 public: |
988 explicit BoyerMoorePositionInfo(Zone* zone) | 961 explicit BoyerMoorePositionInfo(Zone* zone) |
989 : map_(new (zone) ZoneGrowableArray<bool>(kMapSize)), | 962 : map_(new (zone) ZoneGrowableArray<bool>(kMapSize)), |
990 map_count_(0), | 963 map_count_(0), |
991 w_(kNotYet), | 964 w_(kNotYet), |
992 s_(kNotYet), | 965 s_(kNotYet), |
993 d_(kNotYet), | 966 d_(kNotYet), |
994 surrogate_(kNotYet) { | 967 surrogate_(kNotYet) { |
995 for (intptr_t i = 0; i < kMapSize; i++) { | 968 for (intptr_t i = 0; i < kMapSize; i++) { |
(...skipping 16 matching lines...) Expand all Loading... |
1012 | 985 |
1013 private: | 986 private: |
1014 ZoneGrowableArray<bool>* map_; | 987 ZoneGrowableArray<bool>* map_; |
1015 intptr_t map_count_; // Number of set bits in the map. | 988 intptr_t map_count_; // Number of set bits in the map. |
1016 ContainedInLattice w_; // The \w character class. | 989 ContainedInLattice w_; // The \w character class. |
1017 ContainedInLattice s_; // The \s character class. | 990 ContainedInLattice s_; // The \s character class. |
1018 ContainedInLattice d_; // The \d character class. | 991 ContainedInLattice d_; // The \d character class. |
1019 ContainedInLattice surrogate_; // Surrogate UTF-16 code units. | 992 ContainedInLattice surrogate_; // Surrogate UTF-16 code units. |
1020 }; | 993 }; |
1021 | 994 |
1022 | |
1023 class BoyerMooreLookahead : public ZoneAllocated { | 995 class BoyerMooreLookahead : public ZoneAllocated { |
1024 public: | 996 public: |
1025 BoyerMooreLookahead(intptr_t length, RegExpCompiler* compiler, Zone* Zone); | 997 BoyerMooreLookahead(intptr_t length, RegExpCompiler* compiler, Zone* Zone); |
1026 | 998 |
1027 intptr_t length() { return length_; } | 999 intptr_t length() { return length_; } |
1028 intptr_t max_char() { return max_char_; } | 1000 intptr_t max_char() { return max_char_; } |
1029 RegExpCompiler* compiler() { return compiler_; } | 1001 RegExpCompiler* compiler() { return compiler_; } |
1030 | 1002 |
1031 intptr_t Count(intptr_t map_number) { | 1003 intptr_t Count(intptr_t map_number) { |
1032 return bitmaps_->At(map_number)->map_count(); | 1004 return bitmaps_->At(map_number)->map_count(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 intptr_t GetSkipTable(intptr_t min_lookahead, | 1044 intptr_t GetSkipTable(intptr_t min_lookahead, |
1073 intptr_t max_lookahead, | 1045 intptr_t max_lookahead, |
1074 const TypedData& boolean_skip_table); | 1046 const TypedData& boolean_skip_table); |
1075 bool FindWorthwhileInterval(intptr_t* from, intptr_t* to); | 1047 bool FindWorthwhileInterval(intptr_t* from, intptr_t* to); |
1076 intptr_t FindBestInterval(intptr_t max_number_of_chars, | 1048 intptr_t FindBestInterval(intptr_t max_number_of_chars, |
1077 intptr_t old_biggest_points, | 1049 intptr_t old_biggest_points, |
1078 intptr_t* from, | 1050 intptr_t* from, |
1079 intptr_t* to); | 1051 intptr_t* to); |
1080 }; | 1052 }; |
1081 | 1053 |
1082 | |
1083 // There are many ways to generate code for a node. This class encapsulates | 1054 // There are many ways to generate code for a node. This class encapsulates |
1084 // the current way we should be generating. In other words it encapsulates | 1055 // the current way we should be generating. In other words it encapsulates |
1085 // the current state of the code generator. The effect of this is that we | 1056 // the current state of the code generator. The effect of this is that we |
1086 // generate code for paths that the matcher can take through the regular | 1057 // generate code for paths that the matcher can take through the regular |
1087 // expression. A given node in the regexp can be code-generated several times | 1058 // expression. A given node in the regexp can be code-generated several times |
1088 // as it can be part of several traces. For example for the regexp: | 1059 // as it can be part of several traces. For example for the regexp: |
1089 // /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part | 1060 // /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part |
1090 // of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The code | 1061 // of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The code |
1091 // to match foo is generated only once (the traces have a common prefix). The | 1062 // to match foo is generated only once (the traces have a common prefix). The |
1092 // code to store the capture is deferred and generated (twice) after the places | 1063 // code to store the capture is deferred and generated (twice) after the places |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 BlockLabel* loop_label_; | 1216 BlockLabel* loop_label_; |
1246 intptr_t characters_preloaded_; | 1217 intptr_t characters_preloaded_; |
1247 intptr_t bound_checked_up_to_; | 1218 intptr_t bound_checked_up_to_; |
1248 QuickCheckDetails quick_check_performed_; | 1219 QuickCheckDetails quick_check_performed_; |
1249 intptr_t flush_budget_; | 1220 intptr_t flush_budget_; |
1250 TriBool at_start_; | 1221 TriBool at_start_; |
1251 | 1222 |
1252 DISALLOW_ALLOCATION(); | 1223 DISALLOW_ALLOCATION(); |
1253 }; | 1224 }; |
1254 | 1225 |
1255 | |
1256 class GreedyLoopState { | 1226 class GreedyLoopState { |
1257 public: | 1227 public: |
1258 explicit GreedyLoopState(bool not_at_start); | 1228 explicit GreedyLoopState(bool not_at_start); |
1259 | 1229 |
1260 BlockLabel* label() { return &label_; } | 1230 BlockLabel* label() { return &label_; } |
1261 Trace* counter_backtrack_trace() { return &counter_backtrack_trace_; } | 1231 Trace* counter_backtrack_trace() { return &counter_backtrack_trace_; } |
1262 | 1232 |
1263 private: | 1233 private: |
1264 BlockLabel label_; | 1234 BlockLabel label_; |
1265 Trace counter_backtrack_trace_; | 1235 Trace counter_backtrack_trace_; |
1266 }; | 1236 }; |
1267 | 1237 |
1268 | |
1269 struct PreloadState { | 1238 struct PreloadState { |
1270 static const intptr_t kEatsAtLeastNotYetInitialized = -1; | 1239 static const intptr_t kEatsAtLeastNotYetInitialized = -1; |
1271 bool preload_is_current_; | 1240 bool preload_is_current_; |
1272 bool preload_has_checked_bounds_; | 1241 bool preload_has_checked_bounds_; |
1273 intptr_t preload_characters_; | 1242 intptr_t preload_characters_; |
1274 intptr_t eats_at_least_; | 1243 intptr_t eats_at_least_; |
1275 void init() { eats_at_least_ = kEatsAtLeastNotYetInitialized; } | 1244 void init() { eats_at_least_ = kEatsAtLeastNotYetInitialized; } |
1276 | 1245 |
1277 DISALLOW_ALLOCATION(); | 1246 DISALLOW_ALLOCATION(); |
1278 }; | 1247 }; |
1279 | 1248 |
1280 | |
1281 class NodeVisitor : public ValueObject { | 1249 class NodeVisitor : public ValueObject { |
1282 public: | 1250 public: |
1283 virtual ~NodeVisitor() {} | 1251 virtual ~NodeVisitor() {} |
1284 #define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that) = 0; | 1252 #define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that) = 0; |
1285 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1253 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
1286 #undef DECLARE_VISIT | 1254 #undef DECLARE_VISIT |
1287 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } | 1255 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } |
1288 }; | 1256 }; |
1289 | 1257 |
1290 | |
1291 // Assertion propagation moves information about assertions such as | 1258 // Assertion propagation moves information about assertions such as |
1292 // \b to the affected nodes. For instance, in /.\b./ information must | 1259 // \b to the affected nodes. For instance, in /.\b./ information must |
1293 // be propagated to the first '.' that whatever follows needs to know | 1260 // be propagated to the first '.' that whatever follows needs to know |
1294 // if it matched a word or a non-word, and to the second '.' that it | 1261 // if it matched a word or a non-word, and to the second '.' that it |
1295 // has to check if it succeeds a word or non-word. In this case the | 1262 // has to check if it succeeds a word or non-word. In this case the |
1296 // result will be something like: | 1263 // result will be something like: |
1297 // | 1264 // |
1298 // +-------+ +------------+ | 1265 // +-------+ +------------+ |
1299 // | . | | . | | 1266 // | . | | . | |
1300 // +-------+ ---> +------------+ | 1267 // +-------+ ---> +------------+ |
(...skipping 20 matching lines...) Expand all Loading... |
1321 void fail(const char* error_message) { error_message_ = error_message; } | 1288 void fail(const char* error_message) { error_message_ = error_message; } |
1322 | 1289 |
1323 private: | 1290 private: |
1324 bool ignore_case_; | 1291 bool ignore_case_; |
1325 bool is_one_byte_; | 1292 bool is_one_byte_; |
1326 const char* error_message_; | 1293 const char* error_message_; |
1327 | 1294 |
1328 DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis); | 1295 DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis); |
1329 }; | 1296 }; |
1330 | 1297 |
1331 | |
1332 struct RegExpCompileData : public ZoneAllocated { | 1298 struct RegExpCompileData : public ZoneAllocated { |
1333 RegExpCompileData() | 1299 RegExpCompileData() |
1334 : tree(NULL), | 1300 : tree(NULL), |
1335 node(NULL), | 1301 node(NULL), |
1336 simple(true), | 1302 simple(true), |
1337 contains_anchor(false), | 1303 contains_anchor(false), |
1338 error(String::Handle(String::null())), | 1304 error(String::Handle(String::null())), |
1339 capture_count(0) {} | 1305 capture_count(0) {} |
1340 RegExpTree* tree; | 1306 RegExpTree* tree; |
1341 RegExpNode* node; | 1307 RegExpNode* node; |
1342 bool simple; | 1308 bool simple; |
1343 bool contains_anchor; | 1309 bool contains_anchor; |
1344 String& error; | 1310 String& error; |
1345 intptr_t capture_count; | 1311 intptr_t capture_count; |
1346 }; | 1312 }; |
1347 | 1313 |
1348 | |
1349 class RegExpEngine : public AllStatic { | 1314 class RegExpEngine : public AllStatic { |
1350 public: | 1315 public: |
1351 struct CompilationResult { | 1316 struct CompilationResult { |
1352 explicit CompilationResult(const char* error_message) | 1317 explicit CompilationResult(const char* error_message) |
1353 : error_message(error_message), | 1318 : error_message(error_message), |
1354 #if !defined(DART_PRECOMPILED_RUNTIME) | 1319 #if !defined(DART_PRECOMPILED_RUNTIME) |
1355 backtrack_goto(NULL), | 1320 backtrack_goto(NULL), |
1356 graph_entry(NULL), | 1321 graph_entry(NULL), |
1357 num_blocks(-1), | 1322 num_blocks(-1), |
1358 num_stack_locals(-1), | 1323 num_stack_locals(-1), |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1416 const String& pattern, | 1381 const String& pattern, |
1417 bool multi_line, | 1382 bool multi_line, |
1418 bool ignore_case); | 1383 bool ignore_case); |
1419 | 1384 |
1420 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); | 1385 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); |
1421 }; | 1386 }; |
1422 | 1387 |
1423 } // namespace dart | 1388 } // namespace dart |
1424 | 1389 |
1425 #endif // RUNTIME_VM_REGEXP_H_ | 1390 #endif // RUNTIME_VM_REGEXP_H_ |
OLD | NEW |