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

Side by Side Diff: src/jsregexp.h

Issue 18096: Experimental: merge from bleeding_edge. Merge up to and including... (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 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 // The successors are a list of sets that contain the same values 342 // The successors are a list of sets that contain the same values
343 // as this set and the one more value that is not present in this 343 // as this set and the one more value that is not present in this
344 // set. 344 // set.
345 ZoneList<OutSet*>* successors() { return successors_; } 345 ZoneList<OutSet*>* successors() { return successors_; }
346 346
347 OutSet(uint32_t first, ZoneList<unsigned>* remaining) 347 OutSet(uint32_t first, ZoneList<unsigned>* remaining)
348 : first_(first), remaining_(remaining), successors_(NULL) { } 348 : first_(first), remaining_(remaining), successors_(NULL) { }
349 uint32_t first_; 349 uint32_t first_;
350 ZoneList<unsigned>* remaining_; 350 ZoneList<unsigned>* remaining_;
351 ZoneList<OutSet*>* successors_; 351 ZoneList<OutSet*>* successors_;
352 friend class GenerationVariant; 352 friend class Trace;
353 }; 353 };
354 354
355 355
356 // A mapping from integers, specified as ranges, to a set of integers. 356 // A mapping from integers, specified as ranges, to a set of integers.
357 // Used for mapping character ranges to choices. 357 // Used for mapping character ranges to choices.
358 class DispatchTable : public ZoneObject { 358 class DispatchTable : public ZoneObject {
359 public: 359 public:
360 class Entry { 360 class Entry {
361 public: 361 public:
362 Entry() : from_(0), to_(0), out_set_(NULL) { } 362 Entry() : from_(0), to_(0), out_set_(NULL) { }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 int length(); 442 int length();
443 Type type; 443 Type type;
444 union { 444 union {
445 RegExpAtom* u_atom; 445 RegExpAtom* u_atom;
446 RegExpCharacterClass* u_char_class; 446 RegExpCharacterClass* u_char_class;
447 } data; 447 } data;
448 int cp_offset; 448 int cp_offset;
449 }; 449 };
450 450
451 451
452 class GenerationVariant; 452 class Trace;
453 453
454 454
455 struct NodeInfo { 455 struct NodeInfo {
456 enum TriBool { 456 enum TriBool {
457 UNKNOWN = -1, FALSE = 0, TRUE = 1 457 UNKNOWN = -1, FALSE = 0, TRUE = 1
458 }; 458 };
459 459
460 NodeInfo() 460 NodeInfo()
461 : being_analyzed(false), 461 : being_analyzed(false),
462 been_analyzed(false), 462 been_analyzed(false),
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 int characters_; 576 int characters_;
577 Position positions_[4]; 577 Position positions_[4];
578 // These values are the condensate of the above array after Rationalize(). 578 // These values are the condensate of the above array after Rationalize().
579 uint32_t mask_; 579 uint32_t mask_;
580 uint32_t value_; 580 uint32_t value_;
581 }; 581 };
582 582
583 583
584 class RegExpNode: public ZoneObject { 584 class RegExpNode: public ZoneObject {
585 public: 585 public:
586 RegExpNode() : variants_generated_(0) { } 586 RegExpNode() : trace_count_(0) { }
587 virtual ~RegExpNode(); 587 virtual ~RegExpNode();
588 virtual void Accept(NodeVisitor* visitor) = 0; 588 virtual void Accept(NodeVisitor* visitor) = 0;
589 // Generates a goto to this node or actually generates the code at this point. 589 // 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 590 // Until the implementation is complete we will return true for success and
591 // false for failure. 591 // false for failure.
592 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0; 592 virtual bool Emit(RegExpCompiler* compiler, Trace* trace) = 0;
593 // How many characters must this node consume at a minimum in order to 593 // How many characters must this node consume at a minimum in order to
594 // succeed. 594 // succeed.
595 virtual int EatsAtLeast(int recursion_depth) = 0; 595 virtual int EatsAtLeast(int recursion_depth) = 0;
596 // Emits some quick code that checks whether the preloaded characters match. 596 // Emits some quick code that checks whether the preloaded characters match.
597 // Falls through on certain failure, jumps to the label on possible success. 597 // 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. 598 // If the node cannot make a quick check it does nothing and returns false.
599 bool EmitQuickCheck(RegExpCompiler* compiler, 599 bool EmitQuickCheck(RegExpCompiler* compiler,
600 GenerationVariant* variant, 600 Trace* trace,
601 bool preload_has_checked_bounds, 601 bool preload_has_checked_bounds,
602 Label* on_possible_success, 602 Label* on_possible_success,
603 QuickCheckDetails* details_return, 603 QuickCheckDetails* details_return,
604 bool fall_through_on_failure); 604 bool fall_through_on_failure);
605 // For a given number of characters this returns a mask and a value. The 605 // 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. 606 // 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. 607 // A comparison failure indicates the node cannot match the next n characters.
608 // A comparison success indicates the node may match. 608 // A comparison success indicates the node may match.
609 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 609 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
610 RegExpCompiler* compiler, 610 RegExpCompiler* compiler,
611 int characters_filled_in) = 0; 611 int characters_filled_in) = 0;
612 static const int kNodeIsTooComplexForGreedyLoops = -1; 612 static const int kNodeIsTooComplexForGreedyLoops = -1;
613 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 613 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
614 Label* label() { return &label_; } 614 Label* label() { return &label_; }
615 static const int kMaxVariantsGenerated = 10; 615 // 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 // 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 // the deferred actions in the current trace and generating a goto.
620 static const int kMaxCopiesCodeGenerated = 10;
616 621
617 // Propagates the given interest information forward. When seeing 622 // Propagates the given interest information forward. When seeing
618 // \bfoo for instance, the \b is implemented by propagating forward 623 // \bfoo for instance, the \b is implemented by propagating forward
619 // to the 'foo' string that it should only succeed if its first 624 // to the 'foo' string that it should only succeed if its first
620 // character is a letter xor the previous character was a letter. 625 // character is a letter xor the previous character was a letter.
621 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0; 626 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0;
622 627
623 NodeInfo* info() { return &info_; } 628 NodeInfo* info() { return &info_; }
624 629
625 void AddSibling(RegExpNode* node) { siblings_.Add(node); } 630 void AddSibling(RegExpNode* node) { siblings_.Add(node); }
626 631
627 // Static version of EnsureSibling that expresses the fact that the 632 // Static version of EnsureSibling that expresses the fact that the
628 // result has the same type as the input. 633 // result has the same type as the input.
629 template <class C> 634 template <class C>
630 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) { 635 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
631 return static_cast<C*>(node->EnsureSibling(info, cloned)); 636 return static_cast<C*>(node->EnsureSibling(info, cloned));
632 } 637 }
633 638
634 SiblingList* siblings() { return &siblings_; } 639 SiblingList* siblings() { return &siblings_; }
635 void set_siblings(SiblingList* other) { siblings_ = *other; } 640 void set_siblings(SiblingList* other) { siblings_ = *other; }
636 641
637 protected: 642 protected:
638 enum LimitResult { DONE, FAIL, CONTINUE }; 643 enum LimitResult { DONE, FAIL, CONTINUE };
639 LimitResult LimitVersions(RegExpCompiler* compiler, 644 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
640 GenerationVariant* variant);
641 645
642 // Returns a sibling of this node whose interests and assumptions 646 // Returns a sibling of this node whose interests and assumptions
643 // match the ones in the given node info. If no sibling exists NULL 647 // match the ones in the given node info. If no sibling exists NULL
644 // is returned. 648 // is returned.
645 RegExpNode* TryGetSibling(NodeInfo* info); 649 RegExpNode* TryGetSibling(NodeInfo* info);
646 650
647 // Returns a sibling of this node whose interests match the ones in 651 // Returns a sibling of this node whose interests match the ones in
648 // the given node info. The info must not contain any assertions. 652 // the given node info. The info must not contain any assertions.
649 // If no node exists a new one will be created by cloning the current 653 // If no node exists a new one will be created by cloning the current
650 // node. The result will always be an instance of the same concrete 654 // node. The result will always be an instance of the same concrete
651 // class as this node. 655 // class as this node.
652 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned); 656 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned);
653 657
654 // Returns a clone of this node initialized using the copy constructor 658 // Returns a clone of this node initialized using the copy constructor
655 // of its concrete class. Note that the node may have to be pre- 659 // of its concrete class. Note that the node may have to be pre-
656 // processed before it is on a useable state. 660 // processed before it is on a useable state.
657 virtual RegExpNode* Clone() = 0; 661 virtual RegExpNode* Clone() = 0;
658 662
659 private: 663 private:
660 Label label_; 664 Label label_;
661 NodeInfo info_; 665 NodeInfo info_;
662 SiblingList siblings_; 666 SiblingList siblings_;
663 int variants_generated_; 667 // 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
669 // 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
671 // deferred operations in the current trace and generating a goto.
672 int trace_count_;
673 };
674
675
676 // A simple closed interval.
677 class Interval {
678 public:
679 Interval() : from_(kNone), to_(kNone) { }
680 Interval(int from, int to) : from_(from), to_(to) { }
681 Interval Union(Interval that) {
682 if (that.from_ == kNone)
683 return *this;
684 else if (from_ == kNone)
685 return that;
686 else
687 return Interval(Min(from_, that.from_), Max(to_, that.to_));
688 }
689 bool Contains(int value) {
690 return (from_ <= value) && (value <= to_);
691 }
692 bool is_empty() { return from_ == kNone; }
693 int from() { return from_; }
694 int to() { return to_; }
695 static Interval Empty() { return Interval(); }
696 static const int kNone = -1;
697 private:
698 int from_;
699 int to_;
664 }; 700 };
665 701
666 702
667 class SeqRegExpNode: public RegExpNode { 703 class SeqRegExpNode: public RegExpNode {
668 public: 704 public:
669 explicit SeqRegExpNode(RegExpNode* on_success) 705 explicit SeqRegExpNode(RegExpNode* on_success)
670 : on_success_(on_success) { } 706 : on_success_(on_success) { }
671 RegExpNode* on_success() { return on_success_; } 707 RegExpNode* on_success() { return on_success_; }
672 void set_on_success(RegExpNode* node) { on_success_ = node; } 708 void set_on_success(RegExpNode* node) { on_success_ = node; }
673 private: 709 private:
674 RegExpNode* on_success_; 710 RegExpNode* on_success_;
675 }; 711 };
676 712
677 713
678 class ActionNode: public SeqRegExpNode { 714 class ActionNode: public SeqRegExpNode {
679 public: 715 public:
680 enum Type { 716 enum Type {
681 SET_REGISTER, 717 SET_REGISTER,
682 INCREMENT_REGISTER, 718 INCREMENT_REGISTER,
683 STORE_POSITION, 719 STORE_POSITION,
684 BEGIN_SUBMATCH, 720 BEGIN_SUBMATCH,
685 POSITIVE_SUBMATCH_SUCCESS 721 POSITIVE_SUBMATCH_SUCCESS,
722 EMPTY_MATCH_CHECK,
723 CLEAR_CAPTURES
686 }; 724 };
687 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); 725 static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
688 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); 726 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
689 static ActionNode* StorePosition(int reg, RegExpNode* on_success); 727 static ActionNode* StorePosition(int reg, RegExpNode* on_success);
690 static ActionNode* BeginSubmatch( 728 static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
691 int stack_pointer_reg, 729 static ActionNode* BeginSubmatch(int stack_pointer_reg,
692 int position_reg, 730 int position_reg,
693 RegExpNode* on_success); 731 RegExpNode* on_success);
694 static ActionNode* PositiveSubmatchSuccess( 732 static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
695 int stack_pointer_reg, 733 int restore_reg,
696 int restore_reg, 734 RegExpNode* on_success);
697 RegExpNode* on_success); 735 static ActionNode* EmptyMatchCheck(int start_register,
736 int repetition_register,
737 int repetition_limit,
738 RegExpNode* on_success);
698 virtual void Accept(NodeVisitor* visitor); 739 virtual void Accept(NodeVisitor* visitor);
699 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 740 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
700 virtual int EatsAtLeast(int recursion_depth); 741 virtual int EatsAtLeast(int recursion_depth);
701 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 742 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
702 RegExpCompiler* compiler, 743 RegExpCompiler* compiler,
703 int filled_in) { 744 int filled_in) {
704 return on_success()->GetQuickCheckDetails(details, compiler, filled_in); 745 return on_success()->GetQuickCheckDetails(details, compiler, filled_in);
705 } 746 }
706 virtual RegExpNode* PropagateForward(NodeInfo* info); 747 virtual RegExpNode* PropagateForward(NodeInfo* info);
707 Type type() { return type_; } 748 Type type() { return type_; }
708 // TODO(erikcorry): We should allow some action nodes in greedy loops. 749 // TODO(erikcorry): We should allow some action nodes in greedy loops.
709 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 750 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
710 virtual ActionNode* Clone() { return new ActionNode(*this); } 751 virtual ActionNode* Clone() { return new ActionNode(*this); }
711 752
712 private: 753 private:
713 union { 754 union {
714 struct { 755 struct {
715 int reg; 756 int reg;
716 int value; 757 int value;
717 } u_store_register; 758 } u_store_register;
718 struct { 759 struct {
719 int reg; 760 int reg;
720 } u_increment_register; 761 } u_increment_register;
721 struct { 762 struct {
722 int reg; 763 int reg;
723 } u_position_register; 764 } u_position_register;
724 struct { 765 struct {
725 int stack_pointer_register; 766 int stack_pointer_register;
726 int current_position_register; 767 int current_position_register;
727 } u_submatch; 768 } u_submatch;
769 struct {
770 int start_register;
771 int repetition_register;
772 int repetition_limit;
773 } u_empty_match_check;
774 struct {
775 int range_from;
776 int range_to;
777 } u_clear_captures;
728 } data_; 778 } data_;
729 ActionNode(Type type, RegExpNode* on_success) 779 ActionNode(Type type, RegExpNode* on_success)
730 : SeqRegExpNode(on_success), 780 : SeqRegExpNode(on_success),
731 type_(type) { } 781 type_(type) { }
732 Type type_; 782 Type type_;
733 friend class DotPrinter; 783 friend class DotPrinter;
734 }; 784 };
735 785
736 786
737 class TextNode: public SeqRegExpNode { 787 class TextNode: public SeqRegExpNode {
738 public: 788 public:
739 TextNode(ZoneList<TextElement>* elms, 789 TextNode(ZoneList<TextElement>* elms,
740 RegExpNode* on_success) 790 RegExpNode* on_success)
741 : SeqRegExpNode(on_success), 791 : SeqRegExpNode(on_success),
742 elms_(elms) { } 792 elms_(elms) { }
743 TextNode(RegExpCharacterClass* that, 793 TextNode(RegExpCharacterClass* that,
744 RegExpNode* on_success) 794 RegExpNode* on_success)
745 : SeqRegExpNode(on_success), 795 : SeqRegExpNode(on_success),
746 elms_(new ZoneList<TextElement>(1)) { 796 elms_(new ZoneList<TextElement>(1)) {
747 elms_->Add(TextElement::CharClass(that)); 797 elms_->Add(TextElement::CharClass(that));
748 } 798 }
749 virtual void Accept(NodeVisitor* visitor); 799 virtual void Accept(NodeVisitor* visitor);
750 virtual RegExpNode* PropagateForward(NodeInfo* info); 800 virtual RegExpNode* PropagateForward(NodeInfo* info);
751 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 801 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
752 virtual int EatsAtLeast(int recursion_depth); 802 virtual int EatsAtLeast(int recursion_depth);
753 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 803 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
754 RegExpCompiler* compiler, 804 RegExpCompiler* compiler,
755 int characters_filled_in); 805 int characters_filled_in);
756 ZoneList<TextElement>* elements() { return elms_; } 806 ZoneList<TextElement>* elements() { return elms_; }
757 void MakeCaseIndependent(); 807 void MakeCaseIndependent();
758 virtual int GreedyLoopTextLength(); 808 virtual int GreedyLoopTextLength();
759 virtual TextNode* Clone() { 809 virtual TextNode* Clone() {
760 TextNode* result = new TextNode(*this); 810 TextNode* result = new TextNode(*this);
761 result->CalculateOffsets(); 811 result->CalculateOffsets();
762 return result; 812 return result;
763 } 813 }
764 void CalculateOffsets(); 814 void CalculateOffsets();
765 815
766 private: 816 private:
767 enum TextEmitPassType { 817 enum TextEmitPassType {
768 NON_ASCII_MATCH, 818 NON_ASCII_MATCH,
769 CHARACTER_MATCH, 819 CHARACTER_MATCH,
770 CASE_CHARACTER_MATCH, 820 CASE_CHARACTER_MATCH,
771 CHARACTER_CLASS_MATCH 821 CHARACTER_CLASS_MATCH
772 }; 822 };
773 void TextEmitPass(RegExpCompiler* compiler, 823 void TextEmitPass(RegExpCompiler* compiler,
774 TextEmitPassType pass, 824 TextEmitPassType pass,
775 bool preloaded, 825 bool preloaded,
776 GenerationVariant* variant, 826 Trace* trace,
777 bool first_element_checked, 827 bool first_element_checked,
778 int* checked_up_to); 828 int* checked_up_to);
779 int Length(); 829 int Length();
780 ZoneList<TextElement>* elms_; 830 ZoneList<TextElement>* elms_;
781 }; 831 };
782 832
783 833
784 class BackReferenceNode: public SeqRegExpNode { 834 class BackReferenceNode: public SeqRegExpNode {
785 public: 835 public:
786 BackReferenceNode(int start_reg, 836 BackReferenceNode(int start_reg,
787 int end_reg, 837 int end_reg,
788 RegExpNode* on_success) 838 RegExpNode* on_success)
789 : SeqRegExpNode(on_success), 839 : SeqRegExpNode(on_success),
790 start_reg_(start_reg), 840 start_reg_(start_reg),
791 end_reg_(end_reg) { } 841 end_reg_(end_reg) { }
792 virtual void Accept(NodeVisitor* visitor); 842 virtual void Accept(NodeVisitor* visitor);
793 int start_register() { return start_reg_; } 843 int start_register() { return start_reg_; }
794 int end_register() { return end_reg_; } 844 int end_register() { return end_reg_; }
795 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 845 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
796 virtual int EatsAtLeast(int recursion_depth) { return 0; } 846 virtual int EatsAtLeast(int recursion_depth) { return 0; }
797 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 847 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
798 RegExpCompiler* compiler, 848 RegExpCompiler* compiler,
799 int characters_filled_in) { 849 int characters_filled_in) {
800 return; 850 return;
801 } 851 }
802 virtual RegExpNode* PropagateForward(NodeInfo* info); 852 virtual RegExpNode* PropagateForward(NodeInfo* info);
803 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } 853 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
804 854
805 private: 855 private:
806 int start_reg_; 856 int start_reg_;
807 int end_reg_; 857 int end_reg_;
808 }; 858 };
809 859
810 860
811 class EndNode: public RegExpNode { 861 class EndNode: public RegExpNode {
812 public: 862 public:
813 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; 863 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
814 explicit EndNode(Action action) : action_(action) { } 864 explicit EndNode(Action action) : action_(action) { }
815 virtual void Accept(NodeVisitor* visitor); 865 virtual void Accept(NodeVisitor* visitor);
816 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 866 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
817 virtual int EatsAtLeast(int recursion_depth) { return 0; } 867 virtual int EatsAtLeast(int recursion_depth) { return 0; }
818 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 868 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
819 RegExpCompiler* compiler, 869 RegExpCompiler* compiler,
820 int characters_filled_in) { 870 int characters_filled_in) {
821 // Returning 0 from EatsAtLeast should ensure we never get here. 871 // Returning 0 from EatsAtLeast should ensure we never get here.
822 UNREACHABLE(); 872 UNREACHABLE();
823 } 873 }
824 virtual RegExpNode* PropagateForward(NodeInfo* info); 874 virtual RegExpNode* PropagateForward(NodeInfo* info);
825 virtual EndNode* Clone() { return new EndNode(*this); } 875 virtual EndNode* Clone() { return new EndNode(*this); }
826 876
827 protected: 877 protected:
828 void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant); 878 void EmitInfoChecks(RegExpMacroAssembler* macro, Trace* trace);
829 879
830 private: 880 private:
831 Action action_; 881 Action action_;
832 }; 882 };
833 883
834 884
835 class NegativeSubmatchSuccess: public EndNode { 885 class NegativeSubmatchSuccess: public EndNode {
836 public: 886 public:
837 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg) 887 NegativeSubmatchSuccess(int stack_pointer_reg, int position_reg)
838 : EndNode(NEGATIVE_SUBMATCH_SUCCESS), 888 : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
839 stack_pointer_register_(stack_pointer_reg), 889 stack_pointer_register_(stack_pointer_reg),
840 current_position_register_(position_reg) { } 890 current_position_register_(position_reg) { }
841 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 891 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
842 892
843 private: 893 private:
844 int stack_pointer_register_; 894 int stack_pointer_register_;
845 int current_position_register_; 895 int current_position_register_;
846 }; 896 };
847 897
848 898
849 class Guard: public ZoneObject { 899 class Guard: public ZoneObject {
850 public: 900 public:
851 enum Relation { LT, GEQ }; 901 enum Relation { LT, GEQ };
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 class ChoiceNode: public RegExpNode { 934 class ChoiceNode: public RegExpNode {
885 public: 935 public:
886 explicit ChoiceNode(int expected_size) 936 explicit ChoiceNode(int expected_size)
887 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), 937 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
888 table_(NULL), 938 table_(NULL),
889 being_calculated_(false) { } 939 being_calculated_(false) { }
890 virtual void Accept(NodeVisitor* visitor); 940 virtual void Accept(NodeVisitor* visitor);
891 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } 941 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
892 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } 942 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
893 DispatchTable* GetTable(bool ignore_case); 943 DispatchTable* GetTable(bool ignore_case);
894 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 944 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
895 virtual int EatsAtLeast(int recursion_depth); 945 virtual int EatsAtLeast(int recursion_depth);
896 int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node); 946 int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node);
897 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 947 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
898 RegExpCompiler* compiler, 948 RegExpCompiler* compiler,
899 int characters_filled_in); 949 int characters_filled_in);
900 virtual RegExpNode* PropagateForward(NodeInfo* info); 950 virtual RegExpNode* PropagateForward(NodeInfo* info);
901 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } 951 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
902 952
903 bool being_calculated() { return being_calculated_; } 953 bool being_calculated() { return being_calculated_; }
904 void set_being_calculated(bool b) { being_calculated_ = b; } 954 void set_being_calculated(bool b) { being_calculated_ = b; }
905 955
906 protected: 956 protected:
907 int GreedyLoopTextLength(GuardedAlternative *alternative); 957 int GreedyLoopTextLength(GuardedAlternative *alternative);
908 ZoneList<GuardedAlternative>* alternatives_; 958 ZoneList<GuardedAlternative>* alternatives_;
909 959
910 private: 960 private:
911 friend class DispatchTableConstructor; 961 friend class DispatchTableConstructor;
912 friend class Analysis; 962 friend class Analysis;
913 void GenerateGuard(RegExpMacroAssembler* macro_assembler, 963 void GenerateGuard(RegExpMacroAssembler* macro_assembler,
914 Guard *guard, 964 Guard *guard,
915 GenerationVariant* variant); 965 Trace* trace);
916 int CalculatePreloadCharacters(RegExpCompiler* compiler); 966 int CalculatePreloadCharacters(RegExpCompiler* compiler);
917 bool EmitOutOfLineContinuation(RegExpCompiler* compiler, 967 bool EmitOutOfLineContinuation(RegExpCompiler* compiler,
918 GenerationVariant* variant, 968 Trace* trace,
919 GuardedAlternative alternative, 969 GuardedAlternative alternative,
920 AlternativeGeneration* alt_gen, 970 AlternativeGeneration* alt_gen,
921 int preload_characters, 971 int preload_characters,
922 bool next_expects_preload); 972 bool next_expects_preload);
923 DispatchTable* table_; 973 DispatchTable* table_;
924 bool being_calculated_; 974 bool being_calculated_;
925 }; 975 };
926 976
927 977
928 class LoopChoiceNode: public ChoiceNode { 978 class LoopChoiceNode: public ChoiceNode {
929 public: 979 public:
930 explicit LoopChoiceNode(bool body_can_be_zero_length) 980 explicit LoopChoiceNode(bool body_can_be_zero_length)
931 : ChoiceNode(2), 981 : ChoiceNode(2),
932 loop_node_(NULL), 982 loop_node_(NULL),
933 continue_node_(NULL), 983 continue_node_(NULL),
934 body_can_be_zero_length_(body_can_be_zero_length) { } 984 body_can_be_zero_length_(body_can_be_zero_length) { }
935 void AddLoopAlternative(GuardedAlternative alt); 985 void AddLoopAlternative(GuardedAlternative alt);
936 void AddContinueAlternative(GuardedAlternative alt); 986 void AddContinueAlternative(GuardedAlternative alt);
937 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 987 virtual bool Emit(RegExpCompiler* compiler, Trace* trace);
938 virtual int EatsAtLeast(int recursion_depth); // Returns 0. 988 virtual int EatsAtLeast(int recursion_depth); // Returns 0.
939 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 989 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
940 RegExpCompiler* compiler, 990 RegExpCompiler* compiler,
941 int characters_filled_in); 991 int characters_filled_in);
942 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } 992 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
943 RegExpNode* loop_node() { return loop_node_; } 993 RegExpNode* loop_node() { return loop_node_; }
944 RegExpNode* continue_node() { return continue_node_; } 994 RegExpNode* continue_node() { return continue_node_; }
945 bool body_can_be_zero_length() { return body_can_be_zero_length_; } 995 bool body_can_be_zero_length() { return body_can_be_zero_length_; }
946 virtual void Accept(NodeVisitor* visitor); 996 virtual void Accept(NodeVisitor* visitor);
947 997
948 private: 998 private:
949 // AddAlternative is made private for loop nodes because alternatives 999 // AddAlternative is made private for loop nodes because alternatives
950 // should not be added freely, we need to keep track of which node 1000 // should not be added freely, we need to keep track of which node
951 // goes back to the node itself. 1001 // goes back to the node itself.
952 void AddAlternative(GuardedAlternative node) { 1002 void AddAlternative(GuardedAlternative node) {
953 ChoiceNode::AddAlternative(node); 1003 ChoiceNode::AddAlternative(node);
954 } 1004 }
955 1005
956 RegExpNode* loop_node_; 1006 RegExpNode* loop_node_;
957 RegExpNode* continue_node_; 1007 RegExpNode* continue_node_;
958 bool body_can_be_zero_length_; 1008 bool body_can_be_zero_length_;
959 }; 1009 };
960 1010
961 1011
962 // There are many ways to generate code for a node. This class encapsulates 1012 // There are many ways to generate code for a node. This class encapsulates
963 // the current way we should be generating. In other words it encapsulates 1013 // the current way we should be generating. In other words it encapsulates
964 // the current state of the code generator. 1014 // the current state of the code generator. The effect of this is that we
965 class GenerationVariant { 1015 // generate code for paths that the matcher can take through the regular
1016 // expression. A given node in the regexp can be code-generated several times
1017 // as it can be part of several traces. For example for the regexp:
1018 // /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part
1019 // of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The code
1020 // to match foo is generated only once (the traces have a common prefix). The
1021 // code to store the capture is deferred and generated (twice) after the places
1022 // where baz has been matched.
1023 class Trace {
966 public: 1024 public:
967 class DeferredAction { 1025 class DeferredAction {
968 public: 1026 public:
969 DeferredAction(ActionNode::Type type, int reg) 1027 DeferredAction(ActionNode::Type type, int reg)
970 : type_(type), reg_(reg), next_(NULL) { } 1028 : type_(type), reg_(reg), next_(NULL) { }
971 DeferredAction* next() { return next_; } 1029 DeferredAction* next() { return next_; }
1030 bool Mentions(int reg);
972 int reg() { return reg_; } 1031 int reg() { return reg_; }
973 ActionNode::Type type() { return type_; } 1032 ActionNode::Type type() { return type_; }
974 private: 1033 private:
975 ActionNode::Type type_; 1034 ActionNode::Type type_;
976 int reg_; 1035 int reg_;
977 DeferredAction* next_; 1036 DeferredAction* next_;
978 friend class GenerationVariant; 1037 friend class Trace;
979 }; 1038 };
980 1039
981 class DeferredCapture: public DeferredAction { 1040 class DeferredCapture: public DeferredAction {
982 public: 1041 public:
983 DeferredCapture(int reg, GenerationVariant* variant) 1042 DeferredCapture(int reg, Trace* trace)
984 : DeferredAction(ActionNode::STORE_POSITION, reg), 1043 : DeferredAction(ActionNode::STORE_POSITION, reg),
985 cp_offset_(variant->cp_offset()) { } 1044 cp_offset_(trace->cp_offset()) { }
986 int cp_offset() { return cp_offset_; } 1045 int cp_offset() { return cp_offset_; }
987 private: 1046 private:
988 int cp_offset_; 1047 int cp_offset_;
989 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } 1048 void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
990 }; 1049 };
991 1050
992 class DeferredSetRegister :public DeferredAction { 1051 class DeferredSetRegister :public DeferredAction {
993 public: 1052 public:
994 DeferredSetRegister(int reg, int value) 1053 DeferredSetRegister(int reg, int value)
995 : DeferredAction(ActionNode::SET_REGISTER, reg), 1054 : DeferredAction(ActionNode::SET_REGISTER, reg),
996 value_(value) { } 1055 value_(value) { }
997 int value() { return value_; } 1056 int value() { return value_; }
998 private: 1057 private:
999 int value_; 1058 int value_;
1000 }; 1059 };
1001 1060
1061 class DeferredClearCaptures : public DeferredAction {
1062 public:
1063 explicit DeferredClearCaptures(Interval range)
1064 : DeferredAction(ActionNode::CLEAR_CAPTURES, -1),
1065 range_(range) { }
1066 Interval range() { return range_; }
1067 private:
1068 Interval range_;
1069 };
1070
1002 class DeferredIncrementRegister: public DeferredAction { 1071 class DeferredIncrementRegister: public DeferredAction {
1003 public: 1072 public:
1004 explicit DeferredIncrementRegister(int reg) 1073 explicit DeferredIncrementRegister(int reg)
1005 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } 1074 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
1006 }; 1075 };
1007 1076
1008 GenerationVariant() 1077 Trace()
1009 : cp_offset_(0), 1078 : cp_offset_(0),
1010 actions_(NULL), 1079 actions_(NULL),
1011 backtrack_(NULL), 1080 backtrack_(NULL),
1012 stop_node_(NULL), 1081 stop_node_(NULL),
1013 loop_label_(NULL), 1082 loop_label_(NULL),
1014 characters_preloaded_(0), 1083 characters_preloaded_(0),
1015 bound_checked_up_to_(0) { } 1084 bound_checked_up_to_(0) { }
1085 // 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
1087 // done we can start a new trace or go to one that has already been
1088 // generated.
1016 bool Flush(RegExpCompiler* compiler, RegExpNode* successor); 1089 bool Flush(RegExpCompiler* compiler, RegExpNode* successor);
1017 int cp_offset() { return cp_offset_; } 1090 int cp_offset() { return cp_offset_; }
1018 DeferredAction* actions() { return actions_; } 1091 DeferredAction* actions() { return actions_; }
1092 // 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
1094 // 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
1096 // 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
1098 // 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
1100 // a trivial trace is recorded in a label in the node so that gotos can be
1101 // generated to that code.
1019 bool is_trivial() { 1102 bool is_trivial() {
1020 return backtrack_ == NULL && 1103 return backtrack_ == NULL &&
1021 actions_ == NULL && 1104 actions_ == NULL &&
1022 cp_offset_ == 0 && 1105 cp_offset_ == 0 &&
1023 characters_preloaded_ == 0 && 1106 characters_preloaded_ == 0 &&
1024 bound_checked_up_to_ == 0 && 1107 bound_checked_up_to_ == 0 &&
1025 quick_check_performed_.characters() == 0; 1108 quick_check_performed_.characters() == 0;
1026 } 1109 }
1027 Label* backtrack() { return backtrack_; } 1110 Label* backtrack() { return backtrack_; }
1028 Label* loop_label() { return loop_label_; } 1111 Label* loop_label() { return loop_label_; }
1029 RegExpNode* stop_node() { return stop_node_; } 1112 RegExpNode* stop_node() { return stop_node_; }
1030 int characters_preloaded() { return characters_preloaded_; } 1113 int characters_preloaded() { return characters_preloaded_; }
1031 int bound_checked_up_to() { return bound_checked_up_to_; } 1114 int bound_checked_up_to() { return bound_checked_up_to_; }
1032 QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; } 1115 QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
1033 bool mentions_reg(int reg); 1116 bool mentions_reg(int reg);
1034 // These set methods and AdvanceVariant should be used only on new 1117 // Returns true if a deferred position store exists to the specified
1035 // GenerationVariants - the intention is that GenerationVariants are 1118 // register and stores the offset in the out-parameter. Otherwise
1036 // immutable after creation. 1119 // returns false.
1120 bool GetStoredPosition(int reg, int* cp_offset);
1121 // These set methods and AdvanceCurrentPositionInTrace should be used only on
1122 // new traces - the intention is that traces are immutable after creation.
1037 void add_action(DeferredAction* new_action) { 1123 void add_action(DeferredAction* new_action) {
1038 ASSERT(new_action->next_ == NULL); 1124 ASSERT(new_action->next_ == NULL);
1039 new_action->next_ = actions_; 1125 new_action->next_ = actions_;
1040 actions_ = new_action; 1126 actions_ = new_action;
1041 } 1127 }
1042 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; } 1128 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
1043 void set_stop_node(RegExpNode* node) { stop_node_ = node; } 1129 void set_stop_node(RegExpNode* node) { stop_node_ = node; }
1044 void set_loop_label(Label* label) { loop_label_ = label; } 1130 void set_loop_label(Label* label) { loop_label_ = label; }
1045 void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; } 1131 void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
1046 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } 1132 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
1047 void set_quick_check_performed(QuickCheckDetails* d) { 1133 void set_quick_check_performed(QuickCheckDetails* d) {
1048 quick_check_performed_ = *d; 1134 quick_check_performed_ = *d;
1049 } 1135 }
1050 void clear_quick_check_performed() { 1136 void clear_quick_check_performed() {
1051 } 1137 }
1052 void AdvanceVariant(int by, bool ascii); 1138 void AdvanceCurrentPositionInTrace(int by, bool ascii);
1053 private: 1139 private:
1054 int FindAffectedRegisters(OutSet* affected_registers); 1140 int FindAffectedRegisters(OutSet* affected_registers);
1055 void PerformDeferredActions(RegExpMacroAssembler* macro, 1141 void PerformDeferredActions(RegExpMacroAssembler* macro,
1056 int max_register, 1142 int max_register,
1057 OutSet& affected_registers); 1143 OutSet& affected_registers);
1058 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, 1144 void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1059 int max_register, 1145 int max_register,
1060 OutSet& affected_registers); 1146 OutSet& affected_registers);
1061 void PushAffectedRegisters(RegExpMacroAssembler* macro, 1147 void PushAffectedRegisters(RegExpMacroAssembler* macro,
1062 int max_register, 1148 int max_register,
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 Handle<String> pattern, 1254 Handle<String> pattern,
1169 bool is_ascii); 1255 bool is_ascii);
1170 1256
1171 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); 1257 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1172 }; 1258 };
1173 1259
1174 1260
1175 } } // namespace v8::internal 1261 } } // namespace v8::internal
1176 1262
1177 #endif // V8_JSREGEXP_H_ 1263 #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