Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 // The successors are a list of sets that contain the same values | 339 // The successors are a list of sets that contain the same values |
| 340 // as this set and the one more value that is not present in this | 340 // as this set and the one more value that is not present in this |
| 341 // set. | 341 // set. |
| 342 ZoneList<OutSet*>* successors() { return successors_; } | 342 ZoneList<OutSet*>* successors() { return successors_; } |
| 343 | 343 |
| 344 OutSet(uint32_t first, ZoneList<unsigned>* remaining) | 344 OutSet(uint32_t first, ZoneList<unsigned>* remaining) |
| 345 : first_(first), remaining_(remaining), successors_(NULL) { } | 345 : first_(first), remaining_(remaining), successors_(NULL) { } |
| 346 uint32_t first_; | 346 uint32_t first_; |
| 347 ZoneList<unsigned>* remaining_; | 347 ZoneList<unsigned>* remaining_; |
| 348 ZoneList<OutSet*>* successors_; | 348 ZoneList<OutSet*>* successors_; |
| 349 friend class GenerationVariant; | |
| 349 }; | 350 }; |
| 350 | 351 |
| 351 | 352 |
| 352 // A mapping from integers, specified as ranges, to a set of integers. | 353 // A mapping from integers, specified as ranges, to a set of integers. |
| 353 // Used for mapping character ranges to choices. | 354 // Used for mapping character ranges to choices. |
| 354 class DispatchTable : public ZoneObject { | 355 class DispatchTable : public ZoneObject { |
| 355 public: | 356 public: |
| 356 class Entry { | 357 class Entry { |
| 357 public: | 358 public: |
| 358 Entry() : from_(0), to_(0), out_set_(NULL) { } | 359 Entry() : from_(0), to_(0), out_set_(NULL) { } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 | 426 |
| 426 #define FORWARD_DECLARE(Name) class RegExp##Name; | 427 #define FORWARD_DECLARE(Name) class RegExp##Name; |
| 427 FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE) | 428 FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE) |
| 428 #undef FORWARD_DECLARE | 429 #undef FORWARD_DECLARE |
| 429 | 430 |
| 430 | 431 |
| 431 class TextElement { | 432 class TextElement { |
| 432 public: | 433 public: |
| 433 enum Type {UNINITIALIZED, ATOM, CHAR_CLASS}; | 434 enum Type {UNINITIALIZED, ATOM, CHAR_CLASS}; |
| 434 TextElement() : type(UNINITIALIZED) { } | 435 TextElement() : type(UNINITIALIZED) { } |
| 435 explicit TextElement(Type t) : type(t) { } | 436 explicit TextElement(Type t) : type(t), cp_offset(-1) { } |
| 436 static TextElement Atom(RegExpAtom* atom); | 437 static TextElement Atom(RegExpAtom* atom); |
| 437 static TextElement CharClass(RegExpCharacterClass* char_class); | 438 static TextElement CharClass(RegExpCharacterClass* char_class); |
| 438 Type type; | 439 Type type; |
| 439 union { | 440 union { |
| 440 RegExpAtom* u_atom; | 441 RegExpAtom* u_atom; |
| 441 RegExpCharacterClass* u_char_class; | 442 RegExpCharacterClass* u_char_class; |
| 442 } data; | 443 } data; |
| 444 int cp_offset; | |
| 443 }; | 445 }; |
| 444 | 446 |
| 445 | 447 |
| 448 class GenerationVariant; | |
| 449 | |
| 450 | |
| 446 struct NodeInfo { | 451 struct NodeInfo { |
| 447 enum TriBool { | 452 enum TriBool { |
| 448 UNKNOWN = -1, FALSE = 0, TRUE = 1 | 453 UNKNOWN = -1, FALSE = 0, TRUE = 1 |
| 449 }; | 454 }; |
| 450 | 455 |
| 451 NodeInfo() | 456 NodeInfo() |
| 452 : being_analyzed(false), | 457 : being_analyzed(false), |
| 453 been_analyzed(false), | 458 been_analyzed(false), |
| 454 being_expanded(false), | 459 being_expanded(false), |
| 455 been_expanded(false), | 460 been_expanded(false), |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 } | 605 } |
| 601 void Add(RegExpNode* node) { list_->Add(node); } | 606 void Add(RegExpNode* node) { list_->Add(node); } |
| 602 RegExpNode* Get(int index) { return list_->at(index); } | 607 RegExpNode* Get(int index) { return list_->at(index); } |
| 603 private: | 608 private: |
| 604 ZoneList<RegExpNode*>* list_; | 609 ZoneList<RegExpNode*>* list_; |
| 605 }; | 610 }; |
| 606 | 611 |
| 607 | 612 |
| 608 class RegExpNode: public ZoneObject { | 613 class RegExpNode: public ZoneObject { |
| 609 public: | 614 public: |
| 615 RegExpNode() : variants_generated_(0) { } | |
| 610 virtual ~RegExpNode() { } | 616 virtual ~RegExpNode() { } |
| 611 virtual void Accept(NodeVisitor* visitor) = 0; | 617 virtual void Accept(NodeVisitor* visitor) = 0; |
| 612 // Generates a goto to this node or actually generates the code at this point. | 618 // Generates a goto to this node or actually generates the code at this point. |
| 613 // Until the implementation is complete we will return true for success and | 619 // Until the implementation is complete we will return true for success and |
| 614 // false for failure. | 620 // false for failure. |
| 615 virtual bool GoTo(RegExpCompiler* compiler); | 621 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0; |
| 616 Label* label(); | 622 static const int kNodeIsTooComplexForGreedyLoops = -1; |
| 617 | 623 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 618 // Until the implementation is complete we will return true for success and | 624 Label* label() { return &label_; } |
| 619 // false for failure. | 625 static const int kMaxVariantsGenerated = 10; |
| 620 virtual bool Emit(RegExpCompiler* compiler) = 0; | |
| 621 | 626 |
| 622 RegExpNode* EnsureExpanded(NodeInfo* info); | 627 RegExpNode* EnsureExpanded(NodeInfo* info); |
| 623 virtual RegExpNode* ExpandLocal(NodeInfo* info) = 0; | 628 virtual RegExpNode* ExpandLocal(NodeInfo* info) = 0; |
| 624 virtual void ExpandChildren() = 0; | 629 virtual void ExpandChildren() = 0; |
| 625 | 630 |
| 626 // Propagates the given interest information forward. When seeing | 631 // Propagates the given interest information forward. When seeing |
| 627 // \bfoo for instance, the \b is implemented by propagating forward | 632 // \bfoo for instance, the \b is implemented by propagating forward |
| 628 // to the 'foo' string that it should only succeed if its first | 633 // to the 'foo' string that it should only succeed if its first |
| 629 // character is a letter xor the previous character was a letter. | 634 // character is a letter xor the previous character was a letter. |
| 630 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0; | 635 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0; |
| 631 | 636 |
| 632 NodeInfo* info() { return &info_; } | 637 NodeInfo* info() { return &info_; } |
| 633 virtual bool IsBacktrack() { return false; } | |
| 634 | 638 |
| 635 void AddSibling(RegExpNode* node) { siblings_.Add(node); } | 639 void AddSibling(RegExpNode* node) { siblings_.Add(node); } |
| 636 | 640 |
| 637 // Static version of EnsureSibling that expresses the fact that the | 641 // Static version of EnsureSibling that expresses the fact that the |
| 638 // result has the same type as the input. | 642 // result has the same type as the input. |
| 639 template <class C> | 643 template <class C> |
| 640 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) { | 644 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) { |
| 641 return static_cast<C*>(node->EnsureSibling(info, cloned)); | 645 return static_cast<C*>(node->EnsureSibling(info, cloned)); |
| 642 } | 646 } |
| 643 | 647 |
| 644 SiblingList* siblings() { return &siblings_; } | 648 SiblingList* siblings() { return &siblings_; } |
| 645 void set_siblings(SiblingList* other) { siblings_ = *other; } | 649 void set_siblings(SiblingList* other) { siblings_ = *other; } |
| 646 | 650 |
| 647 protected: | 651 protected: |
| 652 enum LimitResult { DONE, FAIL, CONTINUE }; | |
| 653 LimitResult LimitVersions(RegExpCompiler* compiler, | |
| 654 GenerationVariant* variant); | |
| 648 | 655 |
| 649 // Returns a sibling of this node whose interests and assumptions | 656 // Returns a sibling of this node whose interests and assumptions |
| 650 // match the ones in the given node info. If no sibling exists NULL | 657 // match the ones in the given node info. If no sibling exists NULL |
| 651 // is returned. | 658 // is returned. |
| 652 RegExpNode* TryGetSibling(NodeInfo* info); | 659 RegExpNode* TryGetSibling(NodeInfo* info); |
| 653 | 660 |
| 654 // Returns a sibling of this node whose interests match the ones in | 661 // Returns a sibling of this node whose interests match the ones in |
| 655 // the given node info. The info must not contain any assertions. | 662 // the given node info. The info must not contain any assertions. |
| 656 // If no node exists a new one will be created by cloning the current | 663 // If no node exists a new one will be created by cloning the current |
| 657 // node. The result will always be an instance of the same concrete | 664 // node. The result will always be an instance of the same concrete |
| 658 // class as this node. | 665 // class as this node. |
| 659 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned); | 666 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned); |
| 660 | 667 |
| 661 // Returns a clone of this node initialized using the copy constructor | 668 // Returns a clone of this node initialized using the copy constructor |
| 662 // of its concrete class. Note that the node may have to be pre- | 669 // of its concrete class. Note that the node may have to be pre- |
| 663 // processed before it is on a useable state. | 670 // processed before it is on a useable state. |
| 664 virtual RegExpNode* Clone() = 0; | 671 virtual RegExpNode* Clone() = 0; |
| 665 | 672 |
| 666 inline void Bind(RegExpMacroAssembler* macro); | |
| 667 | |
| 668 private: | 673 private: |
| 669 Label label_; | 674 Label label_; |
| 670 NodeInfo info_; | 675 NodeInfo info_; |
| 671 SiblingList siblings_; | 676 SiblingList siblings_; |
| 677 int variants_generated_; | |
| 672 }; | 678 }; |
| 673 | 679 |
| 674 | 680 |
| 675 class SeqRegExpNode: public RegExpNode { | 681 class SeqRegExpNode: public RegExpNode { |
| 676 public: | 682 public: |
| 677 explicit SeqRegExpNode(RegExpNode* on_success) | 683 explicit SeqRegExpNode(RegExpNode* on_success) |
| 678 : on_success_(on_success) { } | 684 : on_success_(on_success) { } |
| 679 RegExpNode* on_success() { return on_success_; } | 685 RegExpNode* on_success() { return on_success_; } |
| 680 void set_on_success(RegExpNode* node) { on_success_ = node; } | 686 void set_on_success(RegExpNode* node) { on_success_ = node; } |
| 681 virtual bool Emit(RegExpCompiler* compiler) { return false; } | |
| 682 private: | 687 private: |
| 683 RegExpNode* on_success_; | 688 RegExpNode* on_success_; |
| 684 }; | 689 }; |
| 685 | 690 |
| 686 | 691 |
| 687 class ActionNode: public SeqRegExpNode { | 692 class ActionNode: public SeqRegExpNode { |
| 688 public: | 693 public: |
| 689 enum Type { | 694 enum Type { |
| 690 STORE_REGISTER, | 695 SET_REGISTER, |
| 691 INCREMENT_REGISTER, | 696 INCREMENT_REGISTER, |
| 692 STORE_POSITION, | 697 STORE_POSITION, |
| 693 RESTORE_POSITION, | |
| 694 BEGIN_SUBMATCH, | 698 BEGIN_SUBMATCH, |
| 695 ESCAPE_SUBMATCH | 699 POSITIVE_SUBMATCH_SUCCESS |
| 696 }; | 700 }; |
| 697 static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success); | 701 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); |
| 698 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); | 702 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); |
| 699 static ActionNode* StorePosition(int reg, RegExpNode* on_success); | 703 static ActionNode* StorePosition(int reg, RegExpNode* on_success); |
| 700 static ActionNode* RestorePosition(int reg, RegExpNode* on_success); | 704 static ActionNode* BeginSubmatch( |
| 701 static ActionNode* BeginSubmatch(int stack_pointer_reg, | 705 int stack_pointer_reg, |
| 702 int position_reg, | 706 int position_reg, |
| 703 RegExpNode* on_success); | 707 RegExpNode* on_success); |
| 704 static ActionNode* EscapeSubmatch(int stack_pointer_reg, | 708 static ActionNode* PositiveSubmatchSuccess( |
| 705 bool and_restore_position, | 709 int stack_pointer_reg, |
| 706 int restore_reg, | 710 int restore_reg, |
| 707 RegExpNode* on_success); | 711 RegExpNode* on_success); |
| 708 virtual void Accept(NodeVisitor* visitor); | 712 virtual void Accept(NodeVisitor* visitor); |
| 709 virtual bool Emit(RegExpCompiler* compiler); | 713 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); |
| 710 virtual RegExpNode* ExpandLocal(NodeInfo* info); | 714 virtual RegExpNode* ExpandLocal(NodeInfo* info); |
| 711 virtual void ExpandChildren(); | 715 virtual void ExpandChildren(); |
| 712 virtual RegExpNode* PropagateForward(NodeInfo* info); | 716 virtual RegExpNode* PropagateForward(NodeInfo* info); |
| 717 Type type() { return type_; } | |
| 718 // TODO(erikcorry): We should allow some action nodes in greedy loops. | |
| 719 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | |
| 713 virtual ActionNode* Clone() { return new ActionNode(*this); } | 720 virtual ActionNode* Clone() { return new ActionNode(*this); } |
| 714 | 721 |
| 715 private: | 722 private: |
| 716 union { | 723 union { |
| 717 struct { | 724 struct { |
| 718 int reg; | 725 int reg; |
| 719 int value; | 726 int value; |
| 720 } u_store_register; | 727 } u_store_register; |
| 721 struct { | 728 struct { |
| 722 int reg; | 729 int reg; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 733 : SeqRegExpNode(on_success), | 740 : SeqRegExpNode(on_success), |
| 734 type_(type) { } | 741 type_(type) { } |
| 735 Type type_; | 742 Type type_; |
| 736 friend class DotPrinter; | 743 friend class DotPrinter; |
| 737 }; | 744 }; |
| 738 | 745 |
| 739 | 746 |
| 740 class TextNode: public SeqRegExpNode { | 747 class TextNode: public SeqRegExpNode { |
| 741 public: | 748 public: |
| 742 TextNode(ZoneList<TextElement>* elms, | 749 TextNode(ZoneList<TextElement>* elms, |
| 743 RegExpNode* on_success, | 750 RegExpNode* on_success) |
| 744 RegExpNode* on_failure) | |
| 745 : SeqRegExpNode(on_success), | 751 : SeqRegExpNode(on_success), |
| 746 on_failure_(on_failure), | |
| 747 elms_(elms) { } | 752 elms_(elms) { } |
| 748 TextNode(RegExpCharacterClass* that, | 753 TextNode(RegExpCharacterClass* that, |
| 749 RegExpNode* on_success, | 754 RegExpNode* on_success) |
| 750 RegExpNode* on_failure) | |
| 751 : SeqRegExpNode(on_success), | 755 : SeqRegExpNode(on_success), |
| 752 on_failure_(on_failure), | |
| 753 elms_(new ZoneList<TextElement>(1)) { | 756 elms_(new ZoneList<TextElement>(1)) { |
| 754 elms_->Add(TextElement::CharClass(that)); | 757 elms_->Add(TextElement::CharClass(that)); |
| 755 } | 758 } |
| 756 virtual void Accept(NodeVisitor* visitor); | 759 virtual void Accept(NodeVisitor* visitor); |
| 757 virtual RegExpNode* PropagateForward(NodeInfo* info); | 760 virtual RegExpNode* PropagateForward(NodeInfo* info); |
| 758 virtual RegExpNode* ExpandLocal(NodeInfo* info); | 761 virtual RegExpNode* ExpandLocal(NodeInfo* info); |
| 759 virtual void ExpandChildren(); | 762 virtual void ExpandChildren(); |
| 760 RegExpNode* on_failure() { return on_failure_; } | 763 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); |
| 761 virtual bool Emit(RegExpCompiler* compiler); | |
| 762 ZoneList<TextElement>* elements() { return elms_; } | 764 ZoneList<TextElement>* elements() { return elms_; } |
| 763 void MakeCaseIndependent(); | 765 void MakeCaseIndependent(); |
| 764 virtual TextNode* Clone() { return new TextNode(*this); } | 766 virtual int GreedyLoopTextLength(); |
| 765 | 767 virtual TextNode* Clone() { |
| 768 TextNode* result = new TextNode(*this); | |
| 769 result->CalculateOffsets(); | |
| 770 return result; | |
| 771 } | |
| 772 void CalculateOffsets(); | |
| 766 private: | 773 private: |
| 767 void ExpandAtomChildren(RegExpAtom* that); | 774 void ExpandAtomChildren(RegExpAtom* that); |
| 768 void ExpandCharClassChildren(RegExpCharacterClass* that); | 775 void ExpandCharClassChildren(RegExpCharacterClass* that); |
| 769 | 776 |
| 770 RegExpNode* on_failure_; | |
| 771 ZoneList<TextElement>* elms_; | 777 ZoneList<TextElement>* elms_; |
| 772 }; | 778 }; |
| 773 | 779 |
| 774 | 780 |
| 775 class BackReferenceNode: public SeqRegExpNode { | 781 class BackReferenceNode: public SeqRegExpNode { |
| 776 public: | 782 public: |
| 777 BackReferenceNode(int start_reg, | 783 BackReferenceNode(int start_reg, |
| 778 int end_reg, | 784 int end_reg, |
| 779 RegExpNode* on_success, | 785 RegExpNode* on_success) |
| 780 RegExpNode* on_failure) | |
| 781 : SeqRegExpNode(on_success), | 786 : SeqRegExpNode(on_success), |
| 782 on_failure_(on_failure), | |
| 783 start_reg_(start_reg), | 787 start_reg_(start_reg), |
| 784 end_reg_(end_reg) { } | 788 end_reg_(end_reg) { } |
| 785 virtual void Accept(NodeVisitor* visitor); | 789 virtual void Accept(NodeVisitor* visitor); |
| 786 RegExpNode* on_failure() { return on_failure_; } | |
| 787 int start_register() { return start_reg_; } | 790 int start_register() { return start_reg_; } |
| 788 int end_register() { return end_reg_; } | 791 int end_register() { return end_reg_; } |
| 789 virtual bool Emit(RegExpCompiler* compiler); | 792 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); |
| 790 virtual RegExpNode* PropagateForward(NodeInfo* info); | 793 virtual RegExpNode* PropagateForward(NodeInfo* info); |
| 791 virtual RegExpNode* ExpandLocal(NodeInfo* info); | 794 virtual RegExpNode* ExpandLocal(NodeInfo* info); |
| 792 virtual void ExpandChildren(); | 795 virtual void ExpandChildren(); |
| 793 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } | 796 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } |
| 794 | 797 |
| 795 private: | 798 private: |
| 796 RegExpNode* on_failure_; | |
| 797 int start_reg_; | 799 int start_reg_; |
| 798 int end_reg_; | 800 int end_reg_; |
| 799 }; | 801 }; |
| 800 | 802 |
| 801 | 803 |
| 802 class EndNode: public RegExpNode { | 804 class EndNode: public RegExpNode { |
| 803 public: | 805 public: |
| 804 enum Action { ACCEPT, BACKTRACK }; | 806 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; |
| 805 explicit EndNode(Action action) : action_(action) { } | 807 explicit EndNode(Action action) : action_(action) { } |
| 806 virtual void Accept(NodeVisitor* visitor); | 808 virtual void Accept(NodeVisitor* visitor); |
| 807 virtual bool Emit(RegExpCompiler* compiler); | 809 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); |
| 808 virtual RegExpNode* PropagateForward(NodeInfo* info); | 810 virtual RegExpNode* PropagateForward(NodeInfo* info); |
| 809 virtual RegExpNode* ExpandLocal(NodeInfo* info); | 811 virtual RegExpNode* ExpandLocal(NodeInfo* info); |
| 810 virtual void ExpandChildren(); | 812 virtual void ExpandChildren(); |
| 811 virtual bool IsBacktrack() { return action_ == BACKTRACK; } | |
| 812 virtual bool GoTo(RegExpCompiler* compiler); | |
| 813 virtual EndNode* Clone() { return new EndNode(*this); } | 813 virtual EndNode* Clone() { return new EndNode(*this); } |
| 814 | 814 |
| 815 protected: | |
| 816 void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant); | |
| 817 | |
| 815 private: | 818 private: |
| 816 Action action_; | 819 Action action_; |
| 817 }; | 820 }; |
| 818 | 821 |
| 819 | 822 |
| 823 class NegativeSubmatchSuccess: public EndNode { | |
| 824 public: | |
| 825 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg) | |
| 826 : EndNode(NEGATIVE_SUBMATCH_SUCCESS), | |
| 827 stack_pointer_register_(stack_pointer_reg), | |
| 828 current_position_register_(position_reg) { } | |
| 829 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); | |
| 830 | |
| 831 private: | |
| 832 int stack_pointer_register_; | |
| 833 int current_position_register_; | |
| 834 }; | |
| 835 | |
| 836 | |
| 820 class Guard: public ZoneObject { | 837 class Guard: public ZoneObject { |
| 821 public: | 838 public: |
| 822 enum Relation { LT, GEQ }; | 839 enum Relation { LT, GEQ }; |
| 823 Guard(int reg, Relation op, int value) | 840 Guard(int reg, Relation op, int value) |
| 824 : reg_(reg), | 841 : reg_(reg), |
| 825 op_(op), | 842 op_(op), |
| 826 value_(value) { } | 843 value_(value) { } |
| 827 int reg() { return reg_; } | 844 int reg() { return reg_; } |
| 828 Relation op() { return op_; } | 845 Relation op() { return op_; } |
| 829 int value() { return value_; } | 846 int value() { return value_; } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 844 ZoneList<Guard*>* guards() { return guards_; } | 861 ZoneList<Guard*>* guards() { return guards_; } |
| 845 | 862 |
| 846 private: | 863 private: |
| 847 RegExpNode* node_; | 864 RegExpNode* node_; |
| 848 ZoneList<Guard*>* guards_; | 865 ZoneList<Guard*>* guards_; |
| 849 }; | 866 }; |
| 850 | 867 |
| 851 | 868 |
| 852 class ChoiceNode: public RegExpNode { | 869 class ChoiceNode: public RegExpNode { |
| 853 public: | 870 public: |
| 854 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) | 871 explicit ChoiceNode(int expected_size) |
| 855 : on_failure_(on_failure), | 872 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), |
| 856 alternatives_(new ZoneList<GuardedAlternative>(expected_size)), | |
| 857 table_(NULL), | 873 table_(NULL), |
| 858 being_calculated_(false) { } | 874 being_calculated_(false) { } |
| 859 virtual void Accept(NodeVisitor* visitor); | 875 virtual void Accept(NodeVisitor* visitor); |
| 860 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } | 876 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } |
| 861 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } | 877 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } |
| 862 DispatchTable* GetTable(bool ignore_case); | 878 DispatchTable* GetTable(bool ignore_case); |
| 863 RegExpNode* on_failure() { return on_failure_; } | 879 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); |
| 864 virtual bool Emit(RegExpCompiler* compiler); | |
| 865 virtual RegExpNode* PropagateForward(NodeInfo* info); | 880 virtual RegExpNode* PropagateForward(NodeInfo* info); |
| 866 virtual RegExpNode* ExpandLocal(NodeInfo* info); | 881 virtual RegExpNode* ExpandLocal(NodeInfo* info); |
| 867 virtual void ExpandChildren(); | 882 virtual void ExpandChildren(); |
| 868 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } | 883 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } |
| 869 | 884 |
| 870 bool being_calculated() { return being_calculated_; } | 885 bool being_calculated() { return being_calculated_; } |
| 871 void set_being_calculated(bool b) { being_calculated_ = b; } | 886 void set_being_calculated(bool b) { being_calculated_ = b; } |
| 872 | 887 |
| 888 protected: | |
| 889 int GreedyLoopTextLength(GuardedAlternative *alternative); | |
| 890 ZoneList<GuardedAlternative>* alternatives_; | |
| 891 | |
| 873 private: | 892 private: |
| 874 friend class DispatchTableConstructor; | 893 friend class DispatchTableConstructor; |
| 875 friend class Analysis; | 894 friend class Analysis; |
| 876 void GenerateGuard(RegExpMacroAssembler* macro_assembler, | 895 void GenerateGuard(RegExpMacroAssembler* macro_assembler, |
| 877 Guard *guard, | 896 Guard *guard, |
| 878 Label* on_failure); | 897 GenerationVariant* variant); |
| 879 RegExpNode* on_failure_; | |
| 880 ZoneList<GuardedAlternative>* alternatives_; | |
| 881 DispatchTable* table_; | 898 DispatchTable* table_; |
| 882 bool being_calculated_; | 899 bool being_calculated_; |
| 883 }; | 900 }; |
| 884 | 901 |
| 885 | 902 |
| 903 class LoopChoiceNode: public ChoiceNode { | |
| 904 public: | |
| 905 explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { } | |
| 906 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); | |
| 907 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } | |
| 908 }; | |
| 909 | |
| 910 | |
| 911 // There are many ways to generate code for a node. This class encapsulates | |
| 912 // the current way we should be generating. In other words it encapsulates | |
| 913 // the current state of the code generator. | |
| 914 class GenerationVariant { | |
|
Christian Plesner Hansen
2008/12/08 08:54:19
Not a fan of this name though I can't think of any
| |
| 915 public: | |
| 916 class DeferredAction { | |
| 917 public: | |
| 918 DeferredAction(ActionNode::Type type, int reg) | |
| 919 : type_(type), reg_(reg), next_(NULL) { } | |
| 920 DeferredAction* next() { return next_; } | |
| 921 int reg() { return reg_; } | |
| 922 ActionNode::Type type() { return type_; } | |
| 923 private: | |
| 924 ActionNode::Type type_; | |
| 925 int reg_; | |
| 926 DeferredAction* next_; | |
| 927 friend class GenerationVariant; | |
| 928 }; | |
| 929 | |
| 930 class DeferredCapture: public DeferredAction { | |
| 931 public: | |
| 932 DeferredCapture(int reg, GenerationVariant* variant) | |
| 933 : DeferredAction(ActionNode::STORE_POSITION, reg), | |
| 934 cp_offset_(variant->cp_offset()) { } | |
| 935 int cp_offset() { return cp_offset_; } | |
| 936 private: | |
| 937 int cp_offset_; | |
| 938 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } | |
| 939 }; | |
| 940 | |
| 941 class DeferredSetRegister :public DeferredAction { | |
| 942 public: | |
| 943 DeferredSetRegister(int reg, int value) | |
| 944 : DeferredAction(ActionNode::SET_REGISTER, reg), | |
| 945 value_(value) { } | |
| 946 int value() { return value_; } | |
| 947 private: | |
| 948 int value_; | |
| 949 }; | |
| 950 | |
| 951 class DeferredIncrementRegister: public DeferredAction { | |
| 952 public: | |
| 953 explicit DeferredIncrementRegister(int reg) | |
| 954 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } | |
| 955 }; | |
| 956 | |
| 957 explicit GenerationVariant(Label* backtrack) | |
| 958 : cp_offset_(0), | |
| 959 actions_(NULL), | |
| 960 backtrack_(backtrack), | |
| 961 stop_node_(NULL), | |
| 962 loop_label_(NULL) { } | |
| 963 GenerationVariant() | |
| 964 : cp_offset_(0), | |
| 965 actions_(NULL), | |
| 966 backtrack_(NULL), | |
| 967 stop_node_(NULL), | |
| 968 loop_label_(NULL) { } | |
| 969 bool Flush(RegExpCompiler* compiler, RegExpNode* successor); | |
| 970 int cp_offset() { return cp_offset_; } | |
| 971 DeferredAction* actions() { return actions_; } | |
| 972 bool is_trivial() { | |
| 973 return backtrack_ == NULL && actions_ == NULL && cp_offset_ == 0; | |
| 974 } | |
| 975 Label* backtrack() { return backtrack_; } | |
| 976 Label* loop_label() { return loop_label_; } | |
| 977 RegExpNode* stop_node() { return stop_node_; } | |
| 978 // These set methods should be used only on new GenerationVariants - the | |
| 979 // intention is that GenerationVariants are immutable after creation. | |
| 980 void add_action(DeferredAction* new_action) { | |
| 981 ASSERT(new_action->next_ == NULL); | |
| 982 new_action->next_ = actions_; | |
| 983 actions_ = new_action; | |
| 984 } | |
| 985 void set_cp_offset(int new_cp_offset) { | |
| 986 ASSERT(new_cp_offset >= cp_offset_); | |
| 987 cp_offset_ = new_cp_offset; | |
| 988 } | |
| 989 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; } | |
| 990 void set_stop_node(RegExpNode* node) { stop_node_ = node; } | |
| 991 void set_loop_label(Label* label) { loop_label_ = label; } | |
| 992 bool mentions_reg(int reg); | |
| 993 private: | |
| 994 int FindAffectedRegisters(OutSet* affected_registers); | |
| 995 void PerformDeferredActions(RegExpMacroAssembler* macro, | |
| 996 int max_register, | |
| 997 OutSet& affected_registers); | |
| 998 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, | |
| 999 int max_register, | |
| 1000 OutSet& affected_registers); | |
| 1001 void PushAffectedRegisters(RegExpMacroAssembler* macro, | |
| 1002 int max_register, | |
| 1003 OutSet& affected_registers); | |
| 1004 int cp_offset_; | |
| 1005 DeferredAction* actions_; | |
| 1006 Label* backtrack_; | |
| 1007 RegExpNode* stop_node_; | |
| 1008 Label* loop_label_; | |
| 1009 }; | |
| 886 class NodeVisitor { | 1010 class NodeVisitor { |
| 887 public: | 1011 public: |
| 888 virtual ~NodeVisitor() { } | 1012 virtual ~NodeVisitor() { } |
| 889 #define DECLARE_VISIT(Type) \ | 1013 #define DECLARE_VISIT(Type) \ |
| 890 virtual void Visit##Type(Type##Node* that) = 0; | 1014 virtual void Visit##Type(Type##Node* that) = 0; |
| 891 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1015 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 892 #undef DECLARE_VISIT | 1016 #undef DECLARE_VISIT |
| 893 }; | 1017 }; |
| 894 | 1018 |
| 895 | 1019 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 Handle<String> error; | 1073 Handle<String> error; |
| 950 int capture_count; | 1074 int capture_count; |
| 951 }; | 1075 }; |
| 952 | 1076 |
| 953 | 1077 |
| 954 class RegExpEngine: public AllStatic { | 1078 class RegExpEngine: public AllStatic { |
| 955 public: | 1079 public: |
| 956 static Handle<FixedArray> Compile(RegExpParseResult* input, | 1080 static Handle<FixedArray> Compile(RegExpParseResult* input, |
| 957 RegExpNode** node_return, | 1081 RegExpNode** node_return, |
| 958 bool ignore_case, | 1082 bool ignore_case, |
| 959 bool multiline); | 1083 bool multiline, |
| 1084 Handle<String> pattern); | |
| 960 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); | 1085 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); |
| 961 }; | 1086 }; |
| 962 | 1087 |
| 963 | 1088 |
| 964 } } // namespace v8::internal | 1089 } } // namespace v8::internal |
| 965 | 1090 |
| 966 #endif // V8_JSREGEXP_H_ | 1091 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |