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 22 matching lines...) Expand all Loading... |
33 #include "ast.h" | 33 #include "ast.h" |
34 #include "execution.h" | 34 #include "execution.h" |
35 #include "factory.h" | 35 #include "factory.h" |
36 #include "jsregexp-inl.h" | 36 #include "jsregexp-inl.h" |
37 #include "platform.h" | 37 #include "platform.h" |
38 #include "runtime.h" | 38 #include "runtime.h" |
39 #include "top.h" | 39 #include "top.h" |
40 #include "compilation-cache.h" | 40 #include "compilation-cache.h" |
41 #include "string-stream.h" | 41 #include "string-stream.h" |
42 #include "parser.h" | 42 #include "parser.h" |
| 43 #include "regexp-macro-assembler.h" |
43 | 44 |
44 // Including pcre.h undefines DEBUG to avoid getting debug output from | 45 // Including pcre.h undefines DEBUG to avoid getting debug output from |
45 // the JSCRE implementation. Make sure to redefine it in debug mode | 46 // the JSCRE implementation. Make sure to redefine it in debug mode |
46 // after having included the header file. | 47 // after having included the header file. |
47 #ifdef DEBUG | 48 #ifdef DEBUG |
48 #include "third_party/jscre/pcre.h" | 49 #include "third_party/jscre/pcre.h" |
49 #define DEBUG | 50 #define DEBUG |
50 #else | 51 #else |
51 #include "third_party/jscre/pcre.h" | 52 #include "third_party/jscre/pcre.h" |
52 #endif | 53 #endif |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 ByteArray* RegExpImpl::JsreInternal(Handle<JSRegExp> re) { | 626 ByteArray* RegExpImpl::JsreInternal(Handle<JSRegExp> re) { |
626 FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex)); | 627 FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex)); |
627 return ByteArray::cast(value->get(INTERNAL_INDEX)); | 628 return ByteArray::cast(value->get(INTERNAL_INDEX)); |
628 } | 629 } |
629 | 630 |
630 | 631 |
631 // ------------------------------------------------------------------- | 632 // ------------------------------------------------------------------- |
632 // New regular expression engine | 633 // New regular expression engine |
633 | 634 |
634 | 635 |
635 class ExecutionState; | 636 class RegExpCompiler; |
| 637 class DotPrinter; |
636 | 638 |
637 | 639 |
638 class RegExpCompiler { | 640 class RegExpCompiler { |
639 public: | 641 public: |
640 explicit RegExpCompiler(int capture_count) | 642 explicit RegExpCompiler(int capture_count) |
641 : next_register_(2 * capture_count) { } | 643 : next_register_(2 * capture_count), |
| 644 work_list_(NULL) { } |
642 | 645 |
643 RegExpNode* Compile(RegExpTree* tree, | 646 RegExpNode* Compile(RegExpTree* tree, |
644 RegExpNode* on_success, | 647 RegExpNode* on_success, |
645 RegExpNode* on_failure); | 648 RegExpNode* on_failure); |
646 | 649 |
647 int AllocateRegister() { return next_register_++; } | 650 int AllocateRegister() { return next_register_++; } |
648 | 651 |
| 652 Handle<FixedArray> Assemble(RegExpMacroAssembler* assembler, |
| 653 RegExpNode* start); |
| 654 |
| 655 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } |
| 656 |
| 657 static const int kImplementationOffset = 0; |
| 658 static const int kNumberOfRegistersOffset = 0; |
| 659 static const int kCodeOffset = 1; |
| 660 |
| 661 RegExpMacroAssembler* macro_assembler() { |
| 662 return macro_assembler_; |
| 663 } |
649 private: | 664 private: |
650 int next_register_; | 665 int next_register_; |
| 666 List<RegExpNode*>* work_list_; |
| 667 RegExpMacroAssembler* macro_assembler_; |
651 }; | 668 }; |
652 | 669 |
653 | 670 |
| 671 Handle<FixedArray> RegExpCompiler::Assemble( |
| 672 RegExpMacroAssembler* macro_assembler, |
| 673 RegExpNode* start) { |
| 674 macro_assembler_ = macro_assembler; |
| 675 List <RegExpNode*> work_list(0); |
| 676 work_list_ = &work_list; |
| 677 start->GoTo(this); |
| 678 while (!work_list.is_empty()) { |
| 679 work_list.RemoveLast()->Emit(this); |
| 680 } |
| 681 Handle<FixedArray> array = Factory::NewFixedArray(3); |
| 682 array->set(kImplementationOffset, |
| 683 Smi::FromInt(macro_assembler->Implementation()), |
| 684 SKIP_WRITE_BARRIER); |
| 685 array->set(kNumberOfRegistersOffset, |
| 686 Smi::FromInt(next_register_), |
| 687 SKIP_WRITE_BARRIER); |
| 688 Handle<Object> code = macro_assembler->GetCode(); |
| 689 work_list_ = NULL; |
| 690 return array; |
| 691 } |
| 692 |
| 693 |
654 #define FOR_EACH_NODE_TYPE(VISIT) \ | 694 #define FOR_EACH_NODE_TYPE(VISIT) \ |
655 VISIT(End) \ | 695 VISIT(End) \ |
656 VISIT(Atom) \ | 696 VISIT(Atom) \ |
657 VISIT(Action) \ | 697 VISIT(Action) \ |
658 VISIT(Choice) \ | 698 VISIT(Choice) \ |
659 VISIT(Backreference) \ | 699 VISIT(Backreference) \ |
660 VISIT(CharacterClass) | 700 VISIT(CharacterClass) |
661 | 701 |
662 | 702 |
663 class RegExpNode: public ZoneObject { | 703 void RegExpNode::GoTo(RegExpCompiler* compiler) { |
664 public: | 704 if (label.is_bound()) { |
665 virtual ~RegExpNode() { } | 705 compiler->macro_assembler()->GoTo(&label); |
666 virtual void Accept(NodeVisitor* visitor) = 0; | 706 } else { |
667 }; | 707 Emit(compiler); |
| 708 } |
| 709 } |
| 710 |
| 711 |
| 712 void RegExpNode::EmitAddress(RegExpCompiler* compiler) { |
| 713 compiler->macro_assembler()->EmitOrLink(&label); |
| 714 } |
668 | 715 |
669 | 716 |
670 class SeqRegExpNode: public RegExpNode { | 717 class SeqRegExpNode: public RegExpNode { |
671 public: | 718 public: |
672 explicit SeqRegExpNode(RegExpNode* on_success) | 719 explicit SeqRegExpNode(RegExpNode* on_success) |
673 : on_success_(on_success) { } | 720 : on_success_(on_success) { } |
674 RegExpNode* on_success() { return on_success_; } | 721 RegExpNode* on_success() { return on_success_; } |
| 722 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
675 private: | 723 private: |
676 RegExpNode* on_success_; | 724 RegExpNode* on_success_; |
677 }; | 725 }; |
678 | 726 |
679 | 727 |
680 class EndNode: public RegExpNode { | 728 class EndNode: public RegExpNode { |
681 public: | 729 public: |
682 enum Action { ACCEPT, BACKTRACK }; | 730 enum Action { ACCEPT, BACKTRACK }; |
683 virtual void Accept(NodeVisitor* visitor); | 731 virtual void Accept(NodeVisitor* visitor); |
684 static EndNode* GetAccept() { return &kAccept; } | 732 static EndNode* GetAccept() { return &kAccept; } |
685 static EndNode* GetBacktrack() { return &kBacktrack; } | 733 static EndNode* GetBacktrack() { return &kBacktrack; } |
| 734 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
686 private: | 735 private: |
687 explicit EndNode(Action action) : action_(action) { } | 736 explicit EndNode(Action action) : action_(action) { } |
688 Action action_; | 737 Action action_; |
689 static EndNode kAccept; | 738 static EndNode kAccept; |
690 static EndNode kBacktrack; | 739 static EndNode kBacktrack; |
691 }; | 740 }; |
692 | 741 |
693 | 742 |
694 EndNode EndNode::kAccept(ACCEPT); | 743 EndNode EndNode::kAccept(ACCEPT); |
695 EndNode EndNode::kBacktrack(BACKTRACK); | 744 EndNode EndNode::kBacktrack(BACKTRACK); |
696 | 745 |
697 | 746 |
698 class AtomNode: public SeqRegExpNode { | 747 class AtomNode: public SeqRegExpNode { |
699 public: | 748 public: |
700 AtomNode(Vector<const uc16> data, | 749 AtomNode(Vector<const uc16> data, |
701 RegExpNode* on_success, | 750 RegExpNode* on_success, |
702 RegExpNode* on_failure) | 751 RegExpNode* on_failure) |
703 : SeqRegExpNode(on_success), | 752 : SeqRegExpNode(on_success), |
704 on_failure_(on_failure), | 753 on_failure_(on_failure), |
705 data_(data) { } | 754 data_(data) { } |
706 virtual void Accept(NodeVisitor* visitor); | 755 virtual void Accept(NodeVisitor* visitor); |
707 Vector<const uc16> data() { return data_; } | 756 Vector<const uc16> data() { return data_; } |
708 RegExpNode* on_failure() { return on_failure_; } | 757 RegExpNode* on_failure() { return on_failure_; } |
| 758 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
709 private: | 759 private: |
710 RegExpNode* on_failure_; | 760 RegExpNode* on_failure_; |
711 Vector<const uc16> data_; | 761 Vector<const uc16> data_; |
712 }; | 762 }; |
713 | 763 |
714 | 764 |
715 class BackreferenceNode: public SeqRegExpNode { | 765 class BackreferenceNode: public SeqRegExpNode { |
716 public: | 766 public: |
717 BackreferenceNode(int start_reg, | 767 BackreferenceNode(int start_reg, |
718 int end_reg, | 768 int end_reg, |
719 RegExpNode* on_success, | 769 RegExpNode* on_success, |
720 RegExpNode* on_failure) | 770 RegExpNode* on_failure) |
721 : SeqRegExpNode(on_success), | 771 : SeqRegExpNode(on_success), |
722 on_failure_(on_failure), | 772 on_failure_(on_failure), |
723 start_reg_(start_reg), | 773 start_reg_(start_reg), |
724 end_reg_(end_reg) { } | 774 end_reg_(end_reg) { } |
725 virtual void Accept(NodeVisitor* visitor); | 775 virtual void Accept(NodeVisitor* visitor); |
726 RegExpNode* on_failure() { return on_failure_; } | 776 RegExpNode* on_failure() { return on_failure_; } |
727 int start_register() { return start_reg_; } | 777 int start_register() { return start_reg_; } |
728 int end_register() { return end_reg_; } | 778 int end_register() { return end_reg_; } |
| 779 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
729 private: | 780 private: |
730 RegExpNode* on_failure_; | 781 RegExpNode* on_failure_; |
731 int start_reg_; | 782 int start_reg_; |
732 int end_reg_; | 783 int end_reg_; |
733 }; | 784 }; |
734 | 785 |
735 | 786 |
736 class CharacterClassNode: public SeqRegExpNode { | 787 class CharacterClassNode: public SeqRegExpNode { |
737 public: | 788 public: |
738 CharacterClassNode(ZoneList<CharacterRange>* ranges, | 789 CharacterClassNode(ZoneList<CharacterRange>* ranges, |
739 bool is_negated, | 790 bool is_negated, |
740 RegExpNode* on_success, | 791 RegExpNode* on_success, |
741 RegExpNode* on_failure) | 792 RegExpNode* on_failure) |
742 : SeqRegExpNode(on_success), | 793 : SeqRegExpNode(on_success), |
743 on_failure_(on_failure), | 794 on_failure_(on_failure), |
744 ranges_(ranges), | 795 ranges_(ranges), |
745 is_negated_(is_negated ){ } | 796 is_negated_(is_negated ) { } |
746 virtual void Accept(NodeVisitor* visitor); | 797 virtual void Accept(NodeVisitor* visitor); |
747 ZoneList<CharacterRange>* ranges() { return ranges_; } | 798 ZoneList<CharacterRange>* ranges() { return ranges_; } |
748 bool is_negated() { return is_negated_; } | 799 bool is_negated() { return is_negated_; } |
749 RegExpNode* on_failure() { return on_failure_; } | 800 RegExpNode* on_failure() { return on_failure_; } |
| 801 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
750 static void AddInverseToTable(List<CharacterRange> ranges, | 802 static void AddInverseToTable(List<CharacterRange> ranges, |
751 DispatchTable* table, | 803 DispatchTable* table, |
752 int index); | 804 int index); |
753 private: | 805 private: |
754 RegExpNode* on_failure_; | 806 RegExpNode* on_failure_; |
755 ZoneList<CharacterRange>* ranges_; | 807 ZoneList<CharacterRange>* ranges_; |
756 bool is_negated_; | 808 bool is_negated_; |
757 }; | 809 }; |
758 | 810 |
759 | 811 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 public: | 849 public: |
798 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) | 850 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) |
799 : on_failure_(on_failure), | 851 : on_failure_(on_failure), |
800 choices_(new ZoneList<GuardedAlternative>(expected_size)), | 852 choices_(new ZoneList<GuardedAlternative>(expected_size)), |
801 visited_(false) { } | 853 visited_(false) { } |
802 virtual void Accept(NodeVisitor* visitor); | 854 virtual void Accept(NodeVisitor* visitor); |
803 void AddChild(GuardedAlternative node) { choices()->Add(node); } | 855 void AddChild(GuardedAlternative node) { choices()->Add(node); } |
804 ZoneList<GuardedAlternative>* choices() { return choices_; } | 856 ZoneList<GuardedAlternative>* choices() { return choices_; } |
805 DispatchTable* table() { return &table_; } | 857 DispatchTable* table() { return &table_; } |
806 RegExpNode* on_failure() { return on_failure_; } | 858 RegExpNode* on_failure() { return on_failure_; } |
| 859 virtual void Emit(RegExpCompiler* compiler); |
807 bool visited() { return visited_; } | 860 bool visited() { return visited_; } |
808 void set_visited(bool value) { visited_ = value; } | 861 void set_visited(bool value) { visited_ = value; } |
809 private: | 862 private: |
810 RegExpNode* on_failure_; | 863 RegExpNode* on_failure_; |
811 ZoneList<GuardedAlternative>* choices_; | 864 ZoneList<GuardedAlternative>* choices_; |
812 DispatchTable table_; | 865 DispatchTable table_; |
813 bool visited_; | 866 bool visited_; |
814 }; | 867 }; |
815 | 868 |
816 | 869 |
817 class ActionNode: public SeqRegExpNode { | 870 class ActionNode: public SeqRegExpNode { |
818 public: | 871 public: |
819 enum Type { | 872 enum Type { |
820 STORE_REGISTER, | 873 STORE_REGISTER, |
821 INCREMENT_REGISTER, | 874 INCREMENT_REGISTER, |
822 STORE_POSITION, | 875 STORE_POSITION, |
823 RESTORE_POSITION, | 876 RESTORE_POSITION, |
824 BEGIN_SUBMATCH, | 877 BEGIN_SUBMATCH, |
825 ESCAPE_SUBMATCH, | 878 ESCAPE_SUBMATCH, |
826 END_SUBMATCH | 879 END_SUBMATCH |
827 }; | 880 }; |
828 static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success); | 881 static ActionNode* StoreRegister(int reg, int val, RegExpNode* on_success); |
829 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); | 882 static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); |
830 static ActionNode* StorePosition(int reg, RegExpNode* on_success); | 883 static ActionNode* StorePosition(int reg, RegExpNode* on_success); |
831 static ActionNode* RestorePosition(int reg, RegExpNode* on_success); | 884 static ActionNode* RestorePosition(int reg, RegExpNode* on_success); |
832 static ActionNode* BeginSubmatch(RegExpNode* on_success); | 885 static ActionNode* BeginSubmatch(RegExpNode* on_success); |
833 static ActionNode* EscapeSubmatch(RegExpNode* on_success); | 886 static ActionNode* EscapeSubmatch(RegExpNode* on_success); |
834 static ActionNode* EndSubmatch(RegExpNode* on_success); | 887 static ActionNode* EndSubmatch(RegExpNode* on_success); |
835 virtual void Accept(NodeVisitor* visitor); | 888 virtual void Accept(NodeVisitor* visitor); |
836 Type type; | 889 virtual void Emit(RegExpCompiler* compiler); |
| 890 private: |
837 union { | 891 union { |
838 struct { | 892 struct { |
839 int reg; | 893 int reg; |
840 int value; | 894 int value; |
841 } u_store_register; | 895 } u_store_register; |
842 struct { | 896 struct { |
843 int reg; | 897 int reg; |
844 } u_increment_register; | 898 } u_increment_register; |
845 struct { | 899 struct { |
846 int reg; | 900 int reg; |
847 } u_position_register; | 901 } u_position_register; |
848 } data; | 902 } data_; |
849 private: | 903 ActionNode(Type type, RegExpNode* on_success) |
850 ActionNode(Type _type, RegExpNode* on_success) | |
851 : SeqRegExpNode(on_success), | 904 : SeqRegExpNode(on_success), |
852 type(_type) { } | 905 type_(type) { } |
| 906 Type type_; |
| 907 friend class DotPrinter; |
853 }; | 908 }; |
854 | 909 |
855 | 910 |
856 ActionNode* ActionNode::StoreRegister(int reg, | 911 ActionNode* ActionNode::StoreRegister(int reg, |
857 int val, | 912 int val, |
858 RegExpNode* on_success) { | 913 RegExpNode* on_success) { |
859 ActionNode* result = new ActionNode(STORE_REGISTER, on_success); | 914 ActionNode* result = new ActionNode(STORE_REGISTER, on_success); |
860 result->data.u_store_register.reg = reg; | 915 result->data_.u_store_register.reg = reg; |
861 result->data.u_store_register.value = val; | 916 result->data_.u_store_register.value = val; |
862 return result; | 917 return result; |
863 } | 918 } |
864 | 919 |
865 | 920 |
866 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { | 921 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { |
867 ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success); | 922 ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success); |
868 result->data.u_increment_register.reg = reg; | 923 result->data_.u_increment_register.reg = reg; |
869 return result; | 924 return result; |
870 } | 925 } |
871 | 926 |
872 | 927 |
873 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { | 928 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { |
874 ActionNode* result = new ActionNode(STORE_POSITION, on_success); | 929 ActionNode* result = new ActionNode(STORE_POSITION, on_success); |
875 result->data.u_position_register.reg = reg; | 930 result->data_.u_position_register.reg = reg; |
876 return result; | 931 return result; |
877 } | 932 } |
878 | 933 |
879 | 934 |
880 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) { | 935 ActionNode* ActionNode::RestorePosition(int reg, RegExpNode* on_success) { |
881 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success); | 936 ActionNode* result = new ActionNode(RESTORE_POSITION, on_success); |
882 result->data.u_position_register.reg = reg; | 937 result->data_.u_position_register.reg = reg; |
883 return result; | 938 return result; |
884 } | 939 } |
885 | 940 |
886 | 941 |
887 ActionNode* ActionNode::BeginSubmatch(RegExpNode* on_success) { | 942 ActionNode* ActionNode::BeginSubmatch(RegExpNode* on_success) { |
888 return new ActionNode(BEGIN_SUBMATCH, on_success); | 943 return new ActionNode(BEGIN_SUBMATCH, on_success); |
889 } | 944 } |
890 | 945 |
891 | 946 |
892 ActionNode* ActionNode::EscapeSubmatch(RegExpNode* on_success) { | 947 ActionNode* ActionNode::EscapeSubmatch(RegExpNode* on_success) { |
(...skipping 18 matching lines...) Expand all Loading... |
911 | 966 |
912 #define DEFINE_ACCEPT(Type) \ | 967 #define DEFINE_ACCEPT(Type) \ |
913 void Type##Node::Accept(NodeVisitor* visitor) { \ | 968 void Type##Node::Accept(NodeVisitor* visitor) { \ |
914 visitor->Visit##Type(this); \ | 969 visitor->Visit##Type(this); \ |
915 } | 970 } |
916 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) | 971 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) |
917 #undef DEFINE_ACCEPT | 972 #undef DEFINE_ACCEPT |
918 | 973 |
919 | 974 |
920 // ------------------------------------------------------------------- | 975 // ------------------------------------------------------------------- |
| 976 // Emit code. |
| 977 |
| 978 |
| 979 void ChoiceNode::Emit(RegExpCompiler* compiler) { |
| 980 // TODO(erikcorry): Implement this. |
| 981 UNREACHABLE(); |
| 982 } |
| 983 |
| 984 |
| 985 void ActionNode::Emit(RegExpCompiler* compiler) { |
| 986 RegExpMacroAssembler* macro = compiler->macro_assembler(); |
| 987 switch (type_) { |
| 988 case STORE_REGISTER: |
| 989 macro->SetRegister(data_.u_store_register.reg, |
| 990 data_.u_store_register.value); |
| 991 break; |
| 992 case INCREMENT_REGISTER: |
| 993 macro->AdvanceRegister(data_.u_increment_register.reg, 1); |
| 994 break; |
| 995 case STORE_POSITION: |
| 996 macro->PushCurrentPosition(); |
| 997 break; |
| 998 case RESTORE_POSITION: |
| 999 macro->PopCurrentPosition(); |
| 1000 break; |
| 1001 case BEGIN_SUBMATCH: |
| 1002 // TODO(erikcorry): Implement this. |
| 1003 UNREACHABLE(); |
| 1004 break; |
| 1005 case ESCAPE_SUBMATCH: |
| 1006 // TODO(erikcorry): Implement this. |
| 1007 UNREACHABLE(); |
| 1008 break; |
| 1009 case END_SUBMATCH: |
| 1010 // TODO(erikcorry): Implement this. |
| 1011 UNREACHABLE(); |
| 1012 break; |
| 1013 } |
| 1014 } |
| 1015 |
| 1016 |
| 1017 // ------------------------------------------------------------------- |
921 // Dot/dotty output | 1018 // Dot/dotty output |
922 | 1019 |
923 | 1020 |
924 #ifdef DEBUG | 1021 #ifdef DEBUG |
925 | 1022 |
926 | 1023 |
927 class DotPrinter: public NodeVisitor { | 1024 class DotPrinter: public NodeVisitor { |
928 public: | 1025 public: |
929 DotPrinter() : stream_(&alloc_) { } | 1026 DotPrinter() : stream_(&alloc_) { } |
930 void PrintNode(const char* label, RegExpNode* node); | 1027 void PrintNode(const char* label, RegExpNode* node); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1041 void DotPrinter::VisitCharacterClass(CharacterClassNode* that) { | 1138 void DotPrinter::VisitCharacterClass(CharacterClassNode* that) { |
1042 stream()->Add(" n%p [label=\"[...]\"];\n", that); | 1139 stream()->Add(" n%p [label=\"[...]\"];\n", that); |
1043 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); | 1140 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); |
1044 Visit(that->on_success()); | 1141 Visit(that->on_success()); |
1045 PrintOnFailure(that, that->on_failure()); | 1142 PrintOnFailure(that, that->on_failure()); |
1046 } | 1143 } |
1047 | 1144 |
1048 | 1145 |
1049 void DotPrinter::VisitAction(ActionNode* that) { | 1146 void DotPrinter::VisitAction(ActionNode* that) { |
1050 stream()->Add(" n%p [", that); | 1147 stream()->Add(" n%p [", that); |
1051 switch (that->type) { | 1148 switch (that->type_) { |
1052 case ActionNode::STORE_REGISTER: | 1149 case ActionNode::STORE_REGISTER: |
1053 stream()->Add("label=\"$%i:=%i\", shape=box", | 1150 stream()->Add("label=\"$%i:=%i\", shape=box", |
1054 that->data.u_store_register.reg, | 1151 that->data_.u_store_register.reg, |
1055 that->data.u_store_register.value); | 1152 that->data_.u_store_register.value); |
1056 break; | 1153 break; |
1057 case ActionNode::INCREMENT_REGISTER: | 1154 case ActionNode::INCREMENT_REGISTER: |
1058 stream()->Add("label=\"$%i++\", shape=box", | 1155 stream()->Add("label=\"$%i++\", shape=box", |
1059 that->data.u_increment_register.reg); | 1156 that->data_.u_increment_register.reg); |
1060 break; | 1157 break; |
1061 case ActionNode::STORE_POSITION: | 1158 case ActionNode::STORE_POSITION: |
1062 stream()->Add("label=\"$%i:=$pos\", shape=box", | 1159 stream()->Add("label=\"$%i:=$pos\", shape=box", |
1063 that->data.u_position_register.reg); | 1160 that->data_.u_position_register.reg); |
1064 break; | 1161 break; |
1065 case ActionNode::RESTORE_POSITION: | 1162 case ActionNode::RESTORE_POSITION: |
1066 stream()->Add("label=\"$pos:=$%i\", shape=box", | 1163 stream()->Add("label=\"$pos:=$%i\", shape=box", |
1067 that->data.u_position_register.reg); | 1164 that->data_.u_position_register.reg); |
1068 break; | 1165 break; |
1069 case ActionNode::BEGIN_SUBMATCH: | 1166 case ActionNode::BEGIN_SUBMATCH: |
1070 stream()->Add("label=\"begin\", shape=septagon"); | 1167 stream()->Add("label=\"begin\", shape=septagon"); |
1071 break; | 1168 break; |
1072 case ActionNode::ESCAPE_SUBMATCH: | 1169 case ActionNode::ESCAPE_SUBMATCH: |
1073 stream()->Add("label=\"escape\", shape=septagon"); | 1170 stream()->Add("label=\"escape\", shape=septagon"); |
1074 break; | 1171 break; |
1075 case ActionNode::END_SUBMATCH: | 1172 case ActionNode::END_SUBMATCH: |
1076 stream()->Add("label=\"end\", shape=septagon"); | 1173 stream()->Add("label=\"end\", shape=septagon"); |
1077 break; | 1174 break; |
1078 } | 1175 } |
1079 stream()->Add("];\n"); | 1176 stream()->Add("];\n"); |
1080 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); | 1177 stream()->Add(" n%p -> n%p;\n", that, that->on_success()); |
1081 Visit(that->on_success()); | 1178 Visit(that->on_success()); |
1082 } | 1179 } |
1083 | 1180 |
1084 | 1181 |
1085 class DispatchTableDumper { | 1182 class DispatchTableDumper { |
1086 public: | 1183 public: |
1087 DispatchTableDumper(StringStream* stream) : stream_(stream) { } | 1184 explicit DispatchTableDumper(StringStream* stream) : stream_(stream) { } |
1088 void Call(uc16 key, DispatchTable::Entry entry); | 1185 void Call(uc16 key, DispatchTable::Entry entry); |
1089 StringStream* stream() { return stream_; } | 1186 StringStream* stream() { return stream_; } |
1090 private: | 1187 private: |
1091 StringStream* stream_; | 1188 StringStream* stream_; |
1092 }; | 1189 }; |
1093 | 1190 |
1094 | 1191 |
1095 void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) { | 1192 void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) { |
1096 stream()->Add("[%k-%k]: {", key, entry.to()); | 1193 stream()->Add("[%k-%k]: {", key, entry.to()); |
1097 OutSet* set = entry.out_set(); | 1194 OutSet* set = entry.out_set(); |
1098 bool first = true; | 1195 bool first = true; |
1099 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) { | 1196 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) { |
1100 if (set->Get(i)) { | 1197 if (set->Get(i)) { |
1101 if (first) first = false; | 1198 if (first) { |
1102 else stream()->Add(", "); | 1199 first = false; |
| 1200 } else { |
| 1201 stream()->Add(", "); |
| 1202 } |
1103 stream()->Add("%i", i); | 1203 stream()->Add("%i", i); |
1104 } | 1204 } |
1105 } | 1205 } |
1106 stream()->Add("}\n"); | 1206 stream()->Add("}\n"); |
1107 } | 1207 } |
1108 | 1208 |
1109 | 1209 |
1110 void DispatchTable::Dump() { | 1210 void DispatchTable::Dump() { |
1111 HeapStringAllocator alloc; | 1211 HeapStringAllocator alloc; |
1112 StringStream stream(&alloc); | 1212 StringStream stream(&alloc); |
1113 tree()->ForEach(DispatchTableDumper(&stream)); | 1213 tree()->ForEach(DispatchTableDumper(&stream)); |
1114 OS::PrintError("%s", *stream.ToCString()); | 1214 OS::PrintError("%s", *stream.ToCString()); |
1115 } | 1215 } |
1116 | 1216 |
1117 | 1217 |
1118 void RegExpEngine::DotPrint(const char* label, RegExpNode* node) { | 1218 void RegExpEngine::DotPrint(const char* label, RegExpNode* node) { |
1119 DotPrinter printer; | 1219 DotPrinter printer; |
1120 printer.PrintNode(label, node); | 1220 printer.PrintNode(label, node); |
1121 } | 1221 } |
1122 | 1222 |
1123 | 1223 |
1124 #endif // DEBUG | 1224 #endif // DEBUG |
1125 | 1225 |
1126 | 1226 |
1127 // ------------------------------------------------------------------- | 1227 // ------------------------------------------------------------------- |
1128 // Tree to graph conversion | 1228 // Tree to graph conversion |
1129 | 1229 |
1130 | 1230 |
1131 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, | 1231 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, |
1132 RegExpNode* on_success, | 1232 RegExpNode* on_success, |
1133 RegExpNode* on_failure) { | 1233 RegExpNode* on_failure) { |
1134 return new AtomNode(data(), on_success, on_failure); | 1234 return new AtomNode(data(), on_success, on_failure); |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 return empty(); | 1621 return empty(); |
1522 } | 1622 } |
1523 | 1623 |
1524 | 1624 |
1525 // ------------------------------------------------------------------- | 1625 // ------------------------------------------------------------------- |
1526 // Analysis | 1626 // Analysis |
1527 | 1627 |
1528 | 1628 |
1529 class Analysis: public NodeVisitor { | 1629 class Analysis: public NodeVisitor { |
1530 public: | 1630 public: |
1531 Analysis(RegExpCompiler* compiler) | 1631 explicit Analysis(RegExpCompiler* compiler) |
1532 : compiler_(compiler), | 1632 : compiler_(compiler), |
1533 table_(NULL), | 1633 table_(NULL), |
1534 choice_index_(-1) { } | 1634 choice_index_(-1) { } |
1535 DispatchTable* table() { return table_; } | 1635 DispatchTable* table() { return table_; } |
1536 RegExpCompiler* compiler() { return compiler_; } | 1636 RegExpCompiler* compiler() { return compiler_; } |
1537 int choice_index() { return choice_index_; } | 1637 int choice_index() { return choice_index_; } |
1538 void Analyze(RegExpNode* node) { node->Accept(this); } | 1638 void Analyze(RegExpNode* node) { node->Accept(this); } |
1539 #define DECLARE_VISIT(Type) \ | 1639 #define DECLARE_VISIT(Type) \ |
1540 virtual void Visit##Type(Type##Node* that); | 1640 virtual void Visit##Type(Type##Node* that); |
1541 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1641 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
1542 #undef DECLARE_VISIT | 1642 #undef DECLARE_VISIT |
1543 protected: | 1643 protected: |
1544 Analysis(Analysis* prev) { *this = *prev; } | 1644 explicit Analysis(Analysis* prev) { *this = *prev; } |
1545 RegExpCompiler* compiler_; | 1645 RegExpCompiler* compiler_; |
1546 DispatchTable *table_; | 1646 DispatchTable *table_; |
1547 int choice_index_; | 1647 int choice_index_; |
1548 }; | 1648 }; |
1549 | 1649 |
1550 | 1650 |
1551 // A subclass of analysis data that allows fields to be set. Anyone | 1651 // A subclass of analysis data that allows fields to be set. Anyone |
1552 // who needs to create new analysis data creates an instance of this | 1652 // who needs to create new analysis data creates an instance of this |
1553 // class, configures it, and then passes it on as an AnalysisData | 1653 // class, configures it, and then passes it on as an AnalysisData |
1554 // which doesn't allow its fields to be changed. | 1654 // which doesn't allow its fields to be changed. |
1555 class AnalysisBuilder: public Analysis { | 1655 class AnalysisBuilder: public Analysis { |
1556 public: | 1656 public: |
1557 AnalysisBuilder(Analysis* prev) : Analysis(prev) { } | 1657 explicit AnalysisBuilder(Analysis* prev) : Analysis(prev) { } |
1558 void set_table(DispatchTable* value) { table_ = value; } | 1658 void set_table(DispatchTable* value) { table_ = value; } |
1559 void set_choice_index(int value) { choice_index_ = value; } | 1659 void set_choice_index(int value) { choice_index_ = value; } |
1560 }; | 1660 }; |
1561 | 1661 |
1562 | 1662 |
1563 void Analysis::VisitEnd(EndNode* that) { | 1663 void Analysis::VisitEnd(EndNode* that) { |
1564 // nothing to do | 1664 // nothing to do |
1565 } | 1665 } |
1566 | 1666 |
1567 | 1667 |
1568 class AddDispatchRange { | 1668 class AddDispatchRange { |
1569 public: | 1669 public: |
1570 AddDispatchRange(Analysis* analysis) : analysis_(analysis) { } | 1670 explicit AddDispatchRange(Analysis* analysis) : analysis_(analysis) { } |
1571 void Call(uc32 from, DispatchTable::Entry entry); | 1671 void Call(uc32 from, DispatchTable::Entry entry); |
1572 private: | 1672 private: |
1573 Analysis* analysis_; | 1673 Analysis* analysis_; |
1574 }; | 1674 }; |
1575 | 1675 |
1576 | 1676 |
1577 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) { | 1677 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) { |
1578 CharacterRange range(from, entry.to()); | 1678 CharacterRange range(from, entry.to()); |
1579 analysis_->table()->AddRange(range, analysis_->choice_index()); | 1679 analysis_->table()->AddRange(range, analysis_->choice_index()); |
1580 } | 1680 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 | 1745 |
1646 RegExpNode* RegExpEngine::Compile(RegExpParseResult* input) { | 1746 RegExpNode* RegExpEngine::Compile(RegExpParseResult* input) { |
1647 RegExpCompiler compiler(input->capture_count); | 1747 RegExpCompiler compiler(input->capture_count); |
1648 RegExpNode* node = compiler.Compile(input->tree, | 1748 RegExpNode* node = compiler.Compile(input->tree, |
1649 EndNode::GetAccept(), | 1749 EndNode::GetAccept(), |
1650 EndNode::GetBacktrack()); | 1750 EndNode::GetBacktrack()); |
1651 return node; | 1751 return node; |
1652 } | 1752 } |
1653 | 1753 |
1654 | 1754 |
| 1755 RegExpMacroAssembler::~RegExpMacroAssembler() { |
| 1756 } |
| 1757 |
| 1758 |
1655 }} // namespace v8::internal | 1759 }} // namespace v8::internal |
OLD | NEW |