| 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 |