Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: src/jsregexp.h

Issue 18842: Experimental: periodic merge of the bleeding_edge branch to the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 ZoneSplayTree<Config>* tree() { return &tree_; } 403 ZoneSplayTree<Config>* tree() { return &tree_; }
404 ZoneSplayTree<Config> tree_; 404 ZoneSplayTree<Config> tree_;
405 }; 405 };
406 406
407 407
408 #define FOR_EACH_NODE_TYPE(VISIT) \ 408 #define FOR_EACH_NODE_TYPE(VISIT) \
409 VISIT(End) \ 409 VISIT(End) \
410 VISIT(Action) \ 410 VISIT(Action) \
411 VISIT(Choice) \ 411 VISIT(Choice) \
412 VISIT(BackReference) \ 412 VISIT(BackReference) \
413 VISIT(Assertion) \
413 VISIT(Text) 414 VISIT(Text)
414 415
415 416
416 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ 417 #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \
417 VISIT(Disjunction) \ 418 VISIT(Disjunction) \
418 VISIT(Alternative) \ 419 VISIT(Alternative) \
419 VISIT(Assertion) \ 420 VISIT(Assertion) \
420 VISIT(CharacterClass) \ 421 VISIT(CharacterClass) \
421 VISIT(Atom) \ 422 VISIT(Atom) \
422 VISIT(Quantifier) \ 423 VISIT(Quantifier) \
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 uint32_t value_; 581 uint32_t value_;
581 }; 582 };
582 583
583 584
584 class RegExpNode: public ZoneObject { 585 class RegExpNode: public ZoneObject {
585 public: 586 public:
586 RegExpNode() : trace_count_(0) { } 587 RegExpNode() : trace_count_(0) { }
587 virtual ~RegExpNode(); 588 virtual ~RegExpNode();
588 virtual void Accept(NodeVisitor* visitor) = 0; 589 virtual void Accept(NodeVisitor* visitor) = 0;
589 // Generates a goto to this node or actually generates the code at this point. 590 // Generates a goto to this node or actually generates the code at this point.
590 // Until the implementation is complete we will return true for success and 591 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
591 // false for failure.
592 virtual bool Emit(RegExpCompiler* compiler, Trace* trace) = 0;
593 // How many characters must this node consume at a minimum in order to 592 // How many characters must this node consume at a minimum in order to
594 // succeed. 593 // succeed. If we have found at least 'still_to_find' characters that
595 virtual int EatsAtLeast(int recursion_depth) = 0; 594 // must be consumed there is no need to ask any following nodes whether
595 // they are sure to eat any more characters.
596 virtual int EatsAtLeast(int still_to_find, int recursion_depth) = 0;
596 // Emits some quick code that checks whether the preloaded characters match. 597 // Emits some quick code that checks whether the preloaded characters match.
597 // Falls through on certain failure, jumps to the label on possible success. 598 // Falls through on certain failure, jumps to the label on possible success.
598 // If the node cannot make a quick check it does nothing and returns false. 599 // If the node cannot make a quick check it does nothing and returns false.
599 bool EmitQuickCheck(RegExpCompiler* compiler, 600 bool EmitQuickCheck(RegExpCompiler* compiler,
600 Trace* trace, 601 Trace* trace,
601 bool preload_has_checked_bounds, 602 bool preload_has_checked_bounds,
602 Label* on_possible_success, 603 Label* on_possible_success,
603 QuickCheckDetails* details_return, 604 QuickCheckDetails* details_return,
604 bool fall_through_on_failure); 605 bool fall_through_on_failure);
605 // For a given number of characters this returns a mask and a value. The 606 // For a given number of characters this returns a mask and a value. The
606 // next n characters are anded with the mask and compared with the value. 607 // next n characters are anded with the mask and compared with the value.
607 // A comparison failure indicates the node cannot match the next n characters. 608 // A comparison failure indicates the node cannot match the next n characters.
608 // A comparison success indicates the node may match. 609 // A comparison success indicates the node may match.
609 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 610 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
610 RegExpCompiler* compiler, 611 RegExpCompiler* compiler,
611 int characters_filled_in) = 0; 612 int characters_filled_in) = 0;
612 static const int kNodeIsTooComplexForGreedyLoops = -1; 613 static const int kNodeIsTooComplexForGreedyLoops = -1;
613 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 614 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
614 Label* label() { return &label_; } 615 Label* label() { return &label_; }
615 // If non-generic code is generated for a node (ie the node is not at the 616 // If non-generic code is generated for a node (ie the node is not at the
616 // start of the trace) then it cannot be reused. This variable sets a limit 617 // start of the trace) then it cannot be reused. This variable sets a limit
617 // on how often we allow that to happen before we insist on starting a new 618 // on how often we allow that to happen before we insist on starting a new
618 // trace and generating generic code for a node that can be reused by flushing 619 // trace and generating generic code for a node that can be reused by flushing
619 // the deferred actions in the current trace and generating a goto. 620 // the deferred actions in the current trace and generating a goto.
620 static const int kMaxCopiesCodeGenerated = 10; 621 static const int kMaxCopiesCodeGenerated = 10;
621 622
622 // Propagates the given interest information forward. When seeing
623 // \bfoo for instance, the \b is implemented by propagating forward
624 // to the 'foo' string that it should only succeed if its first
625 // character is a letter xor the previous character was a letter.
626 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0;
627
628 NodeInfo* info() { return &info_; } 623 NodeInfo* info() { return &info_; }
629 624
630 void AddSibling(RegExpNode* node) { siblings_.Add(node); } 625 void AddSibling(RegExpNode* node) { siblings_.Add(node); }
631 626
632 // Static version of EnsureSibling that expresses the fact that the 627 // Static version of EnsureSibling that expresses the fact that the
633 // result has the same type as the input. 628 // result has the same type as the input.
634 template <class C> 629 template <class C>
635 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) { 630 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
636 return static_cast<C*>(node->EnsureSibling(info, cloned)); 631 return static_cast<C*>(node->EnsureSibling(info, cloned));
637 } 632 }
638 633
639 SiblingList* siblings() { return &siblings_; } 634 SiblingList* siblings() { return &siblings_; }
640 void set_siblings(SiblingList* other) { siblings_ = *other; } 635 void set_siblings(SiblingList* other) { siblings_ = *other; }
641 636
642 protected: 637 protected:
643 enum LimitResult { DONE, FAIL, CONTINUE }; 638 enum LimitResult { DONE, CONTINUE };
644 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); 639 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
645 640
646 // Returns a sibling of this node whose interests and assumptions 641 // Returns a sibling of this node whose interests and assumptions
647 // match the ones in the given node info. If no sibling exists NULL 642 // match the ones in the given node info. If no sibling exists NULL
648 // is returned. 643 // is returned.
649 RegExpNode* TryGetSibling(NodeInfo* info); 644 RegExpNode* TryGetSibling(NodeInfo* info);
650 645
651 // Returns a sibling of this node whose interests match the ones in 646 // Returns a sibling of this node whose interests match the ones in
652 // the given node info. The info must not contain any assertions. 647 // the given node info. The info must not contain any assertions.
653 // If no node exists a new one will be created by cloning the current 648 // If no node exists a new one will be created by cloning the current
654 // node. The result will always be an instance of the same concrete 649 // node. The result will always be an instance of the same concrete
655 // class as this node. 650 // class as this node.
656 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned); 651 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned);
657 652
658 // Returns a clone of this node initialized using the copy constructor 653 // Returns a clone of this node initialized using the copy constructor
659 // of its concrete class. Note that the node may have to be pre- 654 // of its concrete class. Note that the node may have to be pre-
660 // processed before it is on a useable state. 655 // processed before it is on a usable state.
661 virtual RegExpNode* Clone() = 0; 656 virtual RegExpNode* Clone() = 0;
662 657
663 private: 658 private:
664 Label label_; 659 Label label_;
665 NodeInfo info_; 660 NodeInfo info_;
666 SiblingList siblings_; 661 SiblingList siblings_;
667 // This variable keeps track of how many times code has been generated for 662 // This variable keeps track of how many times code has been generated for
668 // this node (in different traces). We don't keep track of where the 663 // this node (in different traces). We don't keep track of where the
669 // generated code is located unless the code is generated at the start of 664 // generated code is located unless the code is generated at the start of
670 // a trace, in which case it is generic and can be reused by flushing the 665 // a trace, in which case it is generic and can be reused by flushing the
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 SET_REGISTER, 712 SET_REGISTER,
718 INCREMENT_REGISTER, 713 INCREMENT_REGISTER,
719 STORE_POSITION, 714 STORE_POSITION,
720 BEGIN_SUBMATCH, 715 BEGIN_SUBMATCH,
721 POSITIVE_SUBMATCH_SUCCESS, 716 POSITIVE_SUBMATCH_SUCCESS,
722 EMPTY_MATCH_CHECK, 717 EMPTY_MATCH_CHECK,
723 CLEAR_CAPTURES 718 CLEAR_CAPTURES
724 }; 719 };
725 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); 720 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
726 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); 721 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
727 static ActionNode* StorePosition(int reg, RegExpNode* on_success); 722 static ActionNode* StorePosition(int reg,
723 bool is_capture,
724 RegExpNode* on_success);
728 static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success); 725 static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
729 static ActionNode* BeginSubmatch(int stack_pointer_reg, 726 static ActionNode* BeginSubmatch(int stack_pointer_reg,
730 int position_reg, 727 int position_reg,
731 RegExpNode* on_success); 728 RegExpNode* on_success);
732 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg, 729 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
733 int restore_reg, 730 int restore_reg,
731 int clear_capture_count,
732 int clear_capture_from,
734 RegExpNode* on_success); 733 RegExpNode* on_success);
735 static ActionNode* EmptyMatchCheck(int start_register, 734 static ActionNode* EmptyMatchCheck(int start_register,
736 int repetition_register, 735 int repetition_register,
737 int repetition_limit, 736 int repetition_limit,
738 RegExpNode* on_success); 737 RegExpNode* on_success);
739 virtual void Accept(NodeVisitor* visitor); 738 virtual void Accept(NodeVisitor* visitor);
740 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 739 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
741 virtual int EatsAtLeast(int recursion_depth); 740 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
742 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 741 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
743 RegExpCompiler* compiler, 742 RegExpCompiler* compiler,
744 int filled_in) { 743 int filled_in) {
745 return on_success()->GetQuickCheckDetails(details, compiler, filled_in); 744 return on_success()->GetQuickCheckDetails(details, compiler, filled_in);
746 } 745 }
747 virtual RegExpNode* PropagateForward(NodeInfo* info);
748 Type type() { return type_; } 746 Type type() { return type_; }
749 // TODO(erikcorry): We should allow some action nodes in greedy loops. 747 // TODO(erikcorry): We should allow some action nodes in greedy loops.
750 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 748 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
751 virtual ActionNode* Clone() { return new ActionNode(*this); } 749 virtual ActionNode* Clone() { return new ActionNode(*this); }
752 750
753 private: 751 private:
754 union { 752 union {
755 struct { 753 struct {
756 int reg; 754 int reg;
757 int value; 755 int value;
758 } u_store_register; 756 } u_store_register;
759 struct { 757 struct {
760 int reg; 758 int reg;
761 } u_increment_register; 759 } u_increment_register;
762 struct { 760 struct {
763 int reg; 761 int reg;
762 bool is_capture;
764 } u_position_register; 763 } u_position_register;
765 struct { 764 struct {
766 int stack_pointer_register; 765 int stack_pointer_register;
767 int current_position_register; 766 int current_position_register;
767 int clear_register_count;
768 int clear_register_from;
768 } u_submatch; 769 } u_submatch;
769 struct { 770 struct {
770 int start_register; 771 int start_register;
771 int repetition_register; 772 int repetition_register;
772 int repetition_limit; 773 int repetition_limit;
773 } u_empty_match_check; 774 } u_empty_match_check;
774 struct { 775 struct {
775 int range_from; 776 int range_from;
776 int range_to; 777 int range_to;
777 } u_clear_captures; 778 } u_clear_captures;
(...skipping 12 matching lines...) Expand all
790 RegExpNode* on_success) 791 RegExpNode* on_success)
791 : SeqRegExpNode(on_success), 792 : SeqRegExpNode(on_success),
792 elms_(elms) { } 793 elms_(elms) { }
793 TextNode(RegExpCharacterClass* that, 794 TextNode(RegExpCharacterClass* that,
794 RegExpNode* on_success) 795 RegExpNode* on_success)
795 : SeqRegExpNode(on_success), 796 : SeqRegExpNode(on_success),
796 elms_(new ZoneList<TextElement>(1)) { 797 elms_(new ZoneList<TextElement>(1)) {
797 elms_->Add(TextElement::CharClass(that)); 798 elms_->Add(TextElement::CharClass(that));
798 } 799 }
799 virtual void Accept(NodeVisitor* visitor); 800 virtual void Accept(NodeVisitor* visitor);
800 virtual RegExpNode* PropagateForward(NodeInfo* info); 801 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
801 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 802 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
802 virtual int EatsAtLeast(int recursion_depth);
803 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 803 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
804 RegExpCompiler* compiler, 804 RegExpCompiler* compiler,
805 int characters_filled_in); 805 int characters_filled_in);
806 ZoneList<TextElement>* elements() { return elms_; } 806 ZoneList<TextElement>* elements() { return elms_; }
807 void MakeCaseIndependent(); 807 void MakeCaseIndependent();
808 virtual int GreedyLoopTextLength(); 808 virtual int GreedyLoopTextLength();
809 virtual TextNode* Clone() { 809 virtual TextNode* Clone() {
810 TextNode* result = new TextNode(*this); 810 TextNode* result = new TextNode(*this);
811 result->CalculateOffsets(); 811 result->CalculateOffsets();
812 return result; 812 return result;
(...skipping 11 matching lines...) Expand all
824 TextEmitPassType pass, 824 TextEmitPassType pass,
825 bool preloaded, 825 bool preloaded,
826 Trace* trace, 826 Trace* trace,
827 bool first_element_checked, 827 bool first_element_checked,
828 int* checked_up_to); 828 int* checked_up_to);
829 int Length(); 829 int Length();
830 ZoneList<TextElement>* elms_; 830 ZoneList<TextElement>* elms_;
831 }; 831 };
832 832
833 833
834 class AssertionNode: public SeqRegExpNode {
835 public:
836 enum AssertionNodeType {
837 AT_END,
838 AT_START,
839 AT_BOUNDARY,
840 AT_NON_BOUNDARY,
841 AFTER_NEWLINE
842 };
843 static AssertionNode* AtEnd(RegExpNode* on_success) {
844 return new AssertionNode(AT_END, on_success);
845 }
846 static AssertionNode* AtStart(RegExpNode* on_success) {
847 return new AssertionNode(AT_START, on_success);
848 }
849 static AssertionNode* AtBoundary(RegExpNode* on_success) {
850 return new AssertionNode(AT_BOUNDARY, on_success);
851 }
852 static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
853 return new AssertionNode(AT_NON_BOUNDARY, on_success);
854 }
855 static AssertionNode* AfterNewline(RegExpNode* on_success) {
856 return new AssertionNode(AFTER_NEWLINE, on_success);
857 }
858 virtual void Accept(NodeVisitor* visitor);
859 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
860 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
861 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
862 RegExpCompiler* compiler,
863 int filled_in) {
864 return on_success()->GetQuickCheckDetails(details, compiler, filled_in);
865 }
866 virtual AssertionNode* Clone() { return new AssertionNode(*this); }
867 AssertionNodeType type() { return type_; }
868 private:
869 AssertionNode(AssertionNodeType t, RegExpNode* on_success)
870 : SeqRegExpNode(on_success), type_(t) { }
871 AssertionNodeType type_;
872 };
873
874
834 class BackReferenceNode: public SeqRegExpNode { 875 class BackReferenceNode: public SeqRegExpNode {
835 public: 876 public:
836 BackReferenceNode(int start_reg, 877 BackReferenceNode(int start_reg,
837 int end_reg, 878 int end_reg,
838 RegExpNode* on_success) 879 RegExpNode* on_success)
839 : SeqRegExpNode(on_success), 880 : SeqRegExpNode(on_success),
840 start_reg_(start_reg), 881 start_reg_(start_reg),
841 end_reg_(end_reg) { } 882 end_reg_(end_reg) { }
842 virtual void Accept(NodeVisitor* visitor); 883 virtual void Accept(NodeVisitor* visitor);
843 int start_register() { return start_reg_; } 884 int start_register() { return start_reg_; }
844 int end_register() { return end_reg_; } 885 int end_register() { return end_reg_; }
845 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 886 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
846 virtual int EatsAtLeast(int recursion_depth) { return 0; } 887 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
847 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 888 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
848 RegExpCompiler* compiler, 889 RegExpCompiler* compiler,
849 int characters_filled_in) { 890 int characters_filled_in) {
850 return; 891 return;
851 } 892 }
852 virtual RegExpNode* PropagateForward(NodeInfo* info);
853 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } 893 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
854 894
855 private: 895 private:
856 int start_reg_; 896 int start_reg_;
857 int end_reg_; 897 int end_reg_;
858 }; 898 };
859 899
860 900
861 class EndNode: public RegExpNode { 901 class EndNode: public RegExpNode {
862 public: 902 public:
863 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; 903 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
864 explicit EndNode(Action action) : action_(action) { } 904 explicit EndNode(Action action) : action_(action) { }
865 virtual void Accept(NodeVisitor* visitor); 905 virtual void Accept(NodeVisitor* visitor);
866 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 906 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
867 virtual int EatsAtLeast(int recursion_depth) { return 0; } 907 virtual int EatsAtLeast(int still_to_find, int recursion_depth) { return 0; }
868 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 908 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
869 RegExpCompiler* compiler, 909 RegExpCompiler* compiler,
870 int characters_filled_in) { 910 int characters_filled_in) {
871 // Returning 0 from EatsAtLeast should ensure we never get here. 911 // Returning 0 from EatsAtLeast should ensure we never get here.
872 UNREACHABLE(); 912 UNREACHABLE();
873 } 913 }
874 virtual RegExpNode* PropagateForward(NodeInfo* info);
875 virtual EndNode* Clone() { return new EndNode(*this); } 914 virtual EndNode* Clone() { return new EndNode(*this); }
876 915
877 protected:
878 void EmitInfoChecks(RegExpMacroAssembler* macro, Trace* trace);
879
880 private: 916 private:
881 Action action_; 917 Action action_;
882 }; 918 };
883 919
884 920
885 class NegativeSubmatchSuccess: public EndNode { 921 class NegativeSubmatchSuccess: public EndNode {
886 public: 922 public:
887 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg) 923 NegativeSubmatchSuccess(int stack_pointer_reg,
924 int position_reg,
925 int clear_capture_count,
926 int clear_capture_start)
888 : EndNode(NEGATIVE_SUBMATCH_SUCCESS), 927 : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
889 stack_pointer_register_(stack_pointer_reg), 928 stack_pointer_register_(stack_pointer_reg),
890 current_position_register_(position_reg) { } 929 current_position_register_(position_reg),
891 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 930 clear_capture_count_(clear_capture_count),
931 clear_capture_start_(clear_capture_start) { }
932 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
892 933
893 private: 934 private:
894 int stack_pointer_register_; 935 int stack_pointer_register_;
895 int current_position_register_; 936 int current_position_register_;
937 int clear_capture_count_;
938 int clear_capture_start_;
896 }; 939 };
897 940
898 941
899 class Guard: public ZoneObject { 942 class Guard: public ZoneObject {
900 public: 943 public:
901 enum Relation { LT, GEQ }; 944 enum Relation { LT, GEQ };
902 Guard(int reg, Relation op, int value) 945 Guard(int reg, Relation op, int value)
903 : reg_(reg), 946 : reg_(reg),
904 op_(op), 947 op_(op),
905 value_(value) { } 948 value_(value) { }
(...skipping 28 matching lines...) Expand all
934 class ChoiceNode: public RegExpNode { 977 class ChoiceNode: public RegExpNode {
935 public: 978 public:
936 explicit ChoiceNode(int expected_size) 979 explicit ChoiceNode(int expected_size)
937 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), 980 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
938 table_(NULL), 981 table_(NULL),
939 being_calculated_(false) { } 982 being_calculated_(false) { }
940 virtual void Accept(NodeVisitor* visitor); 983 virtual void Accept(NodeVisitor* visitor);
941 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } 984 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
942 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } 985 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
943 DispatchTable* GetTable(bool ignore_case); 986 DispatchTable* GetTable(bool ignore_case);
944 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 987 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
945 virtual int EatsAtLeast(int recursion_depth); 988 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
946 int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node); 989 int EatsAtLeastHelper(int still_to_find,
990 int recursion_depth,
991 RegExpNode* ignore_this_node);
947 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 992 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
948 RegExpCompiler* compiler, 993 RegExpCompiler* compiler,
949 int characters_filled_in); 994 int characters_filled_in);
950 virtual RegExpNode* PropagateForward(NodeInfo* info);
951 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } 995 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
952 996
953 bool being_calculated() { return being_calculated_; } 997 bool being_calculated() { return being_calculated_; }
954 void set_being_calculated(bool b) { being_calculated_ = b; } 998 void set_being_calculated(bool b) { being_calculated_ = b; }
999 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
955 1000
956 protected: 1001 protected:
957 int GreedyLoopTextLength(GuardedAlternative *alternative); 1002 int GreedyLoopTextLength(GuardedAlternative *alternative);
958 ZoneList<GuardedAlternative>* alternatives_; 1003 ZoneList<GuardedAlternative>* alternatives_;
959 1004
960 private: 1005 private:
961 friend class DispatchTableConstructor; 1006 friend class DispatchTableConstructor;
962 friend class Analysis; 1007 friend class Analysis;
963 void GenerateGuard(RegExpMacroAssembler* macro_assembler, 1008 void GenerateGuard(RegExpMacroAssembler* macro_assembler,
964 Guard *guard, 1009 Guard *guard,
965 Trace* trace); 1010 Trace* trace);
966 int CalculatePreloadCharacters(RegExpCompiler* compiler); 1011 int CalculatePreloadCharacters(RegExpCompiler* compiler);
967 bool EmitOutOfLineContinuation(RegExpCompiler* compiler, 1012 void EmitOutOfLineContinuation(RegExpCompiler* compiler,
968 Trace* trace, 1013 Trace* trace,
969 GuardedAlternative alternative, 1014 GuardedAlternative alternative,
970 AlternativeGeneration* alt_gen, 1015 AlternativeGeneration* alt_gen,
971 int preload_characters, 1016 int preload_characters,
972 bool next_expects_preload); 1017 bool next_expects_preload);
973 DispatchTable* table_; 1018 DispatchTable* table_;
974 bool being_calculated_; 1019 bool being_calculated_;
975 }; 1020 };
976 1021
977 1022
1023 class NegativeLookaheadChoiceNode: public ChoiceNode {
1024 public:
1025 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
1026 GuardedAlternative then_do_this)
1027 : ChoiceNode(2) {
1028 AddAlternative(this_must_fail);
1029 AddAlternative(then_do_this);
1030 }
1031 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
1032 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1033 RegExpCompiler* compiler,
1034 int characters_filled_in);
1035 // For a negative lookahead we don't emit the quick check for the
1036 // alternative that is expected to fail. This is because quick check code
1037 // starts by loading enough characters for the alternative that takes fewest
1038 // characters, but on a negative lookahead the negative branch did not take
1039 // part in that calculation (EatsAtLeast) so the assumptions don't hold.
1040 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
1041 };
1042
1043
978 class LoopChoiceNode: public ChoiceNode { 1044 class LoopChoiceNode: public ChoiceNode {
979 public: 1045 public:
980 explicit LoopChoiceNode(bool body_can_be_zero_length) 1046 explicit LoopChoiceNode(bool body_can_be_zero_length)
981 : ChoiceNode(2), 1047 : ChoiceNode(2),
982 loop_node_(NULL), 1048 loop_node_(NULL),
983 continue_node_(NULL), 1049 continue_node_(NULL),
984 body_can_be_zero_length_(body_can_be_zero_length) { } 1050 body_can_be_zero_length_(body_can_be_zero_length) { }
985 void AddLoopAlternative(GuardedAlternative alt); 1051 void AddLoopAlternative(GuardedAlternative alt);
986 void AddContinueAlternative(GuardedAlternative alt); 1052 void AddContinueAlternative(GuardedAlternative alt);
987 virtual bool Emit(RegExpCompiler* compiler, Trace* trace); 1053 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
988 virtual int EatsAtLeast(int recursion_depth); // Returns 0. 1054 virtual int EatsAtLeast(int still_to_find, int recursion_depth);
989 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 1055 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
990 RegExpCompiler* compiler, 1056 RegExpCompiler* compiler,
991 int characters_filled_in); 1057 int characters_filled_in);
992 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } 1058 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
993 RegExpNode* loop_node() { return loop_node_; } 1059 RegExpNode* loop_node() { return loop_node_; }
994 RegExpNode* continue_node() { return continue_node_; } 1060 RegExpNode* continue_node() { return continue_node_; }
995 bool body_can_be_zero_length() { return body_can_be_zero_length_; } 1061 bool body_can_be_zero_length() { return body_can_be_zero_length_; }
996 virtual void Accept(NodeVisitor* visitor); 1062 virtual void Accept(NodeVisitor* visitor);
997 1063
998 private: 1064 private:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 bool Mentions(int reg); 1096 bool Mentions(int reg);
1031 int reg() { return reg_; } 1097 int reg() { return reg_; }
1032 ActionNode::Type type() { return type_; } 1098 ActionNode::Type type() { return type_; }
1033 private: 1099 private:
1034 ActionNode::Type type_; 1100 ActionNode::Type type_;
1035 int reg_; 1101 int reg_;
1036 DeferredAction* next_; 1102 DeferredAction* next_;
1037 friend class Trace; 1103 friend class Trace;
1038 }; 1104 };
1039 1105
1040 class DeferredCapture: public DeferredAction { 1106 class DeferredCapture : public DeferredAction {
1041 public: 1107 public:
1042 DeferredCapture(int reg, Trace* trace) 1108 DeferredCapture(int reg, bool is_capture, Trace* trace)
1043 : DeferredAction(ActionNode::STORE_POSITION, reg), 1109 : DeferredAction(ActionNode::STORE_POSITION, reg),
1044 cp_offset_(trace->cp_offset()) { } 1110 cp_offset_(trace->cp_offset()),
1111 is_capture_(is_capture) { }
1045 int cp_offset() { return cp_offset_; } 1112 int cp_offset() { return cp_offset_; }
1113 bool is_capture() { return is_capture_; }
1046 private: 1114 private:
1047 int cp_offset_; 1115 int cp_offset_;
1116 bool is_capture_;
1048 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } 1117 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
1049 }; 1118 };
1050 1119
1051 class DeferredSetRegister :public DeferredAction { 1120 class DeferredSetRegister : public DeferredAction {
1052 public: 1121 public:
1053 DeferredSetRegister(int reg, int value) 1122 DeferredSetRegister(int reg, int value)
1054 : DeferredAction(ActionNode::SET_REGISTER, reg), 1123 : DeferredAction(ActionNode::SET_REGISTER, reg),
1055 value_(value) { } 1124 value_(value) { }
1056 int value() { return value_; } 1125 int value() { return value_; }
1057 private: 1126 private:
1058 int value_; 1127 int value_;
1059 }; 1128 };
1060 1129
1061 class DeferredClearCaptures : public DeferredAction { 1130 class DeferredClearCaptures : public DeferredAction {
1062 public: 1131 public:
1063 explicit DeferredClearCaptures(Interval range) 1132 explicit DeferredClearCaptures(Interval range)
1064 : DeferredAction(ActionNode::CLEAR_CAPTURES, -1), 1133 : DeferredAction(ActionNode::CLEAR_CAPTURES, -1),
1065 range_(range) { } 1134 range_(range) { }
1066 Interval range() { return range_; } 1135 Interval range() { return range_; }
1067 private: 1136 private:
1068 Interval range_; 1137 Interval range_;
1069 }; 1138 };
1070 1139
1071 class DeferredIncrementRegister: public DeferredAction { 1140 class DeferredIncrementRegister : public DeferredAction {
1072 public: 1141 public:
1073 explicit DeferredIncrementRegister(int reg) 1142 explicit DeferredIncrementRegister(int reg)
1074 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } 1143 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
1075 }; 1144 };
1076 1145
1077 Trace() 1146 Trace()
1078 : cp_offset_(0), 1147 : cp_offset_(0),
1079 actions_(NULL), 1148 actions_(NULL),
1080 backtrack_(NULL), 1149 backtrack_(NULL),
1081 stop_node_(NULL), 1150 stop_node_(NULL),
1082 loop_label_(NULL), 1151 loop_label_(NULL),
1083 characters_preloaded_(0), 1152 characters_preloaded_(0),
1084 bound_checked_up_to_(0) { } 1153 bound_checked_up_to_(0) { }
1085 // End the trace. This involves flushing the deferred actions in the trace 1154 // End the trace. This involves flushing the deferred actions in the trace
1086 // and pushing a backtrack location onto the backtrack stack. Once this is 1155 // and pushing a backtrack location onto the backtrack stack. Once this is
1087 // done we can start a new trace or go to one that has already been 1156 // done we can start a new trace or go to one that has already been
1088 // generated. 1157 // generated.
1089 bool Flush(RegExpCompiler* compiler, RegExpNode* successor); 1158 void Flush(RegExpCompiler* compiler, RegExpNode* successor);
1090 int cp_offset() { return cp_offset_; } 1159 int cp_offset() { return cp_offset_; }
1091 DeferredAction* actions() { return actions_; } 1160 DeferredAction* actions() { return actions_; }
1092 // A trivial trace is one that has no deferred actions or other state that 1161 // A trivial trace is one that has no deferred actions or other state that
1093 // affects the assumptions used when generating code. There is no recorded 1162 // affects the assumptions used when generating code. There is no recorded
1094 // backtrack location in a trivial trace, so with a trivial trace we will 1163 // backtrack location in a trivial trace, so with a trivial trace we will
1095 // generate code that, on a failure to match, gets the backtrack location 1164 // generate code that, on a failure to match, gets the backtrack location
1096 // from the backtrack stack rather than using a direct jump instruction. We 1165 // from the backtrack stack rather than using a direct jump instruction. We
1097 // always start code generation with a trivial trace and non-trivial traces 1166 // always start code generation with a trivial trace and non-trivial traces
1098 // are created as we emit code for nodes or add to the list of deferred 1167 // are created as we emit code for nodes or add to the list of deferred
1099 // actions in the trace. The location of the code generated for a node using 1168 // actions in the trace. The location of the code generated for a node using
(...skipping 26 matching lines...) Expand all
1126 actions_ = new_action; 1195 actions_ = new_action;
1127 } 1196 }
1128 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; } 1197 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
1129 void set_stop_node(RegExpNode* node) { stop_node_ = node; } 1198 void set_stop_node(RegExpNode* node) { stop_node_ = node; }
1130 void set_loop_label(Label* label) { loop_label_ = label; } 1199 void set_loop_label(Label* label) { loop_label_ = label; }
1131 void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; } 1200 void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
1132 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } 1201 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
1133 void set_quick_check_performed(QuickCheckDetails* d) { 1202 void set_quick_check_performed(QuickCheckDetails* d) {
1134 quick_check_performed_ = *d; 1203 quick_check_performed_ = *d;
1135 } 1204 }
1136 void clear_quick_check_performed() { 1205 void InvalidateCurrentCharacter();
1137 } 1206 void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler);
1138 void AdvanceCurrentPositionInTrace(int by, bool ascii);
1139 private: 1207 private:
1140 int FindAffectedRegisters(OutSet* affected_registers); 1208 int FindAffectedRegisters(OutSet* affected_registers);
1141 void PerformDeferredActions(RegExpMacroAssembler* macro, 1209 void PerformDeferredActions(RegExpMacroAssembler* macro,
1142 int max_register, 1210 int max_register,
1143 OutSet& affected_registers); 1211 OutSet& affected_registers,
1212 OutSet* registers_to_pop,
1213 OutSet* registers_to_clear);
1144 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, 1214 void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1145 int max_register, 1215 int max_register,
1146 OutSet& affected_registers); 1216 OutSet& registers_to_pop,
1147 void PushAffectedRegisters(RegExpMacroAssembler* macro, 1217 OutSet& registers_to_clear);
1148 int max_register,
1149 OutSet& affected_registers);
1150 int cp_offset_; 1218 int cp_offset_;
1151 DeferredAction* actions_; 1219 DeferredAction* actions_;
1152 Label* backtrack_; 1220 Label* backtrack_;
1153 RegExpNode* stop_node_; 1221 RegExpNode* stop_node_;
1154 Label* loop_label_; 1222 Label* loop_label_;
1155 int characters_preloaded_; 1223 int characters_preloaded_;
1156 int bound_checked_up_to_; 1224 int bound_checked_up_to_;
1157 QuickCheckDetails quick_check_performed_; 1225 QuickCheckDetails quick_check_performed_;
1158 }; 1226 };
1159 1227
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 Handle<String> pattern, 1322 Handle<String> pattern,
1255 bool is_ascii); 1323 bool is_ascii);
1256 1324
1257 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); 1325 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1258 }; 1326 };
1259 1327
1260 1328
1261 } } // namespace v8::internal 1329 } } // namespace v8::internal
1262 1330
1263 #endif // V8_JSREGEXP_H_ 1331 #endif // V8_JSREGEXP_H_
OLDNEW
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698