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 |