| 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 |