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

Side by Side Diff: src/jsregexp.h

Issue 5524006: Irregexp: Preload more characters when we are not at the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years 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 | « no previous file | 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 579 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 public: 590 public:
591 RegExpNode() : first_character_set_(NULL), trace_count_(0) { } 591 RegExpNode() : first_character_set_(NULL), trace_count_(0) { }
592 virtual ~RegExpNode(); 592 virtual ~RegExpNode();
593 virtual void Accept(NodeVisitor* visitor) = 0; 593 virtual void Accept(NodeVisitor* visitor) = 0;
594 // Generates a goto to this node or actually generates the code at this point. 594 // Generates a goto to this node or actually generates the code at this point.
595 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; 595 virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
596 // How many characters must this node consume at a minimum in order to 596 // How many characters must this node consume at a minimum in order to
597 // succeed. If we have found at least 'still_to_find' characters that 597 // succeed. If we have found at least 'still_to_find' characters that
598 // must be consumed there is no need to ask any following nodes whether 598 // must be consumed there is no need to ask any following nodes whether
599 // they are sure to eat any more characters. 599 // they are sure to eat any more characters.
600 virtual int EatsAtLeast(int still_to_find, int recursion_depth) = 0; 600 virtual int EatsAtLeast(int still_to_find,
Lasse Reichstein 2010/12/03 09:12:43 Add explanation of not_at_start parameter - what h
Erik Corry 2010/12/03 09:26:08 I think I will explain, but not rename, since we u
601 int recursion_depth,
602 bool not_at_start) = 0;
601 // Emits some quick code that checks whether the preloaded characters match. 603 // Emits some quick code that checks whether the preloaded characters match.
602 // Falls through on certain failure, jumps to the label on possible success. 604 // Falls through on certain failure, jumps to the label on possible success.
603 // If the node cannot make a quick check it does nothing and returns false. 605 // If the node cannot make a quick check it does nothing and returns false.
604 bool EmitQuickCheck(RegExpCompiler* compiler, 606 bool EmitQuickCheck(RegExpCompiler* compiler,
605 Trace* trace, 607 Trace* trace,
606 bool preload_has_checked_bounds, 608 bool preload_has_checked_bounds,
607 Label* on_possible_success, 609 Label* on_possible_success,
608 QuickCheckDetails* details_return, 610 QuickCheckDetails* details_return,
609 bool fall_through_on_failure); 611 bool fall_through_on_failure);
610 // For a given number of characters this returns a mask and a value. The 612 // For a given number of characters this returns a mask and a value. The
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 int restore_reg, 760 int restore_reg,
759 int clear_capture_count, 761 int clear_capture_count,
760 int clear_capture_from, 762 int clear_capture_from,
761 RegExpNode* on_success); 763 RegExpNode* on_success);
762 static ActionNode* EmptyMatchCheck(int start_register, 764 static ActionNode* EmptyMatchCheck(int start_register,
763 int repetition_register, 765 int repetition_register,
764 int repetition_limit, 766 int repetition_limit,
765 RegExpNode* on_success); 767 RegExpNode* on_success);
766 virtual void Accept(NodeVisitor* visitor); 768 virtual void Accept(NodeVisitor* visitor);
767 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 769 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
768 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 770 virtual int EatsAtLeast(int still_to_find,
771 int recursion_depth,
772 bool not_at_start);
769 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 773 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
770 RegExpCompiler* compiler, 774 RegExpCompiler* compiler,
771 int filled_in, 775 int filled_in,
772 bool not_at_start) { 776 bool not_at_start) {
773 return on_success()->GetQuickCheckDetails( 777 return on_success()->GetQuickCheckDetails(
774 details, compiler, filled_in, not_at_start); 778 details, compiler, filled_in, not_at_start);
775 } 779 }
776 Type type() { return type_; } 780 Type type() { return type_; }
777 // TODO(erikcorry): We should allow some action nodes in greedy loops. 781 // TODO(erikcorry): We should allow some action nodes in greedy loops.
778 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 782 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 : SeqRegExpNode(on_success), 826 : SeqRegExpNode(on_success),
823 elms_(elms) { } 827 elms_(elms) { }
824 TextNode(RegExpCharacterClass* that, 828 TextNode(RegExpCharacterClass* that,
825 RegExpNode* on_success) 829 RegExpNode* on_success)
826 : SeqRegExpNode(on_success), 830 : SeqRegExpNode(on_success),
827 elms_(new ZoneList<TextElement>(1)) { 831 elms_(new ZoneList<TextElement>(1)) {
828 elms_->Add(TextElement::CharClass(that)); 832 elms_->Add(TextElement::CharClass(that));
829 } 833 }
830 virtual void Accept(NodeVisitor* visitor); 834 virtual void Accept(NodeVisitor* visitor);
831 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 835 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
832 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 836 virtual int EatsAtLeast(int still_to_find,
837 int recursion_depth,
838 bool not_at_start);
833 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 839 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
834 RegExpCompiler* compiler, 840 RegExpCompiler* compiler,
835 int characters_filled_in, 841 int characters_filled_in,
836 bool not_at_start); 842 bool not_at_start);
837 ZoneList<TextElement>* elements() { return elms_; } 843 ZoneList<TextElement>* elements() { return elms_; }
838 void MakeCaseIndependent(bool is_ascii); 844 void MakeCaseIndependent(bool is_ascii);
839 virtual int GreedyLoopTextLength(); 845 virtual int GreedyLoopTextLength();
840 virtual TextNode* Clone() { 846 virtual TextNode* Clone() {
841 TextNode* result = new TextNode(*this); 847 TextNode* result = new TextNode(*this);
842 result->CalculateOffsets(); 848 result->CalculateOffsets();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 return new AssertionNode(AT_BOUNDARY, on_success); 896 return new AssertionNode(AT_BOUNDARY, on_success);
891 } 897 }
892 static AssertionNode* AtNonBoundary(RegExpNode* on_success) { 898 static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
893 return new AssertionNode(AT_NON_BOUNDARY, on_success); 899 return new AssertionNode(AT_NON_BOUNDARY, on_success);
894 } 900 }
895 static AssertionNode* AfterNewline(RegExpNode* on_success) { 901 static AssertionNode* AfterNewline(RegExpNode* on_success) {
896 return new AssertionNode(AFTER_NEWLINE, on_success); 902 return new AssertionNode(AFTER_NEWLINE, on_success);
897 } 903 }
898 virtual void Accept(NodeVisitor* visitor); 904 virtual void Accept(NodeVisitor* visitor);
899 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 905 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
900 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 906 virtual int EatsAtLeast(int still_to_find,
907 int recursion_depth,
908 bool not_at_start);
901 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 909 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
902 RegExpCompiler* compiler, 910 RegExpCompiler* compiler,
903 int filled_in, 911 int filled_in,
904 bool not_at_start); 912 bool not_at_start);
905 virtual int ComputeFirstCharacterSet(int budget); 913 virtual int ComputeFirstCharacterSet(int budget);
906 virtual AssertionNode* Clone() { return new AssertionNode(*this); } 914 virtual AssertionNode* Clone() { return new AssertionNode(*this); }
907 AssertionNodeType type() { return type_; } 915 AssertionNodeType type() { return type_; }
908 void set_type(AssertionNodeType type) { type_ = type; } 916 void set_type(AssertionNodeType type) { type_ = type; }
909 private: 917 private:
910 AssertionNode(AssertionNodeType t, RegExpNode* on_success) 918 AssertionNode(AssertionNodeType t, RegExpNode* on_success)
911 : SeqRegExpNode(on_success), type_(t) { } 919 : SeqRegExpNode(on_success), type_(t) { }
912 AssertionNodeType type_; 920 AssertionNodeType type_;
913 }; 921 };
914 922
915 923
916 class BackReferenceNode: public SeqRegExpNode { 924 class BackReferenceNode: public SeqRegExpNode {
917 public: 925 public:
918 BackReferenceNode(int start_reg, 926 BackReferenceNode(int start_reg,
919 int end_reg, 927 int end_reg,
920 RegExpNode* on_success) 928 RegExpNode* on_success)
921 : SeqRegExpNode(on_success), 929 : SeqRegExpNode(on_success),
922 start_reg_(start_reg), 930 start_reg_(start_reg),
923 end_reg_(end_reg) { } 931 end_reg_(end_reg) { }
924 virtual void Accept(NodeVisitor* visitor); 932 virtual void Accept(NodeVisitor* visitor);
925 int start_register() { return start_reg_; } 933 int start_register() { return start_reg_; }
926 int end_register() { return end_reg_; } 934 int end_register() { return end_reg_; }
927 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 935 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
928 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 936 virtual int EatsAtLeast(int still_to_find,
937 int recursion_depth,
938 bool not_at_start);
929 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 939 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
930 RegExpCompiler* compiler, 940 RegExpCompiler* compiler,
931 int characters_filled_in, 941 int characters_filled_in,
932 bool not_at_start) { 942 bool not_at_start) {
933 return; 943 return;
934 } 944 }
935 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } 945 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
936 virtual int ComputeFirstCharacterSet(int budget); 946 virtual int ComputeFirstCharacterSet(int budget);
937 private: 947 private:
938 int start_reg_; 948 int start_reg_;
939 int end_reg_; 949 int end_reg_;
940 }; 950 };
941 951
942 952
943 class EndNode: public RegExpNode { 953 class EndNode: public RegExpNode {
944 public: 954 public:
945 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; 955 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
946 explicit EndNode(Action action) : action_(action) { } 956 explicit EndNode(Action action) : action_(action) { }
947 virtual void Accept(NodeVisitor* visitor); 957 virtual void Accept(NodeVisitor* visitor);
948 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 958 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
949 virtual int EatsAtLeast(int still_to_find, int recursion_depth) { return 0; } 959 virtual int EatsAtLeast(int still_to_find,
960 int recursion_depth,
961 bool not_at_start) { return 0; }
950 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 962 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
951 RegExpCompiler* compiler, 963 RegExpCompiler* compiler,
952 int characters_filled_in, 964 int characters_filled_in,
953 bool not_at_start) { 965 bool not_at_start) {
954 // Returning 0 from EatsAtLeast should ensure we never get here. 966 // Returning 0 from EatsAtLeast should ensure we never get here.
955 UNREACHABLE(); 967 UNREACHABLE();
956 } 968 }
957 virtual EndNode* Clone() { return new EndNode(*this); } 969 virtual EndNode* Clone() { return new EndNode(*this); }
958 private: 970 private:
959 Action action_; 971 Action action_;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 explicit ChoiceNode(int expected_size) 1033 explicit ChoiceNode(int expected_size)
1022 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), 1034 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
1023 table_(NULL), 1035 table_(NULL),
1024 not_at_start_(false), 1036 not_at_start_(false),
1025 being_calculated_(false) { } 1037 being_calculated_(false) { }
1026 virtual void Accept(NodeVisitor* visitor); 1038 virtual void Accept(NodeVisitor* visitor);
1027 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } 1039 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
1028 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } 1040 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
1029 DispatchTable* GetTable(bool ignore_case); 1041 DispatchTable* GetTable(bool ignore_case);
1030 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 1042 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1031 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 1043 virtual int EatsAtLeast(int still_to_find,
1044 int recursion_depth,
1045 bool not_at_start);
1032 int EatsAtLeastHelper(int still_to_find, 1046 int EatsAtLeastHelper(int still_to_find,
1033 int recursion_depth, 1047 int recursion_depth,
1034 RegExpNode* ignore_this_node); 1048 RegExpNode* ignore_this_node,
1049 bool not_at_start);
1035 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 1050 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1036 RegExpCompiler* compiler, 1051 RegExpCompiler* compiler,
1037 int characters_filled_in, 1052 int characters_filled_in,
1038 bool not_at_start); 1053 bool not_at_start);
1039 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } 1054 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
1040 1055
1041 bool being_calculated() { return being_calculated_; } 1056 bool being_calculated() { return being_calculated_; }
1042 bool not_at_start() { return not_at_start_; } 1057 bool not_at_start() { return not_at_start_; }
1043 void set_not_at_start() { not_at_start_ = true; } 1058 void set_not_at_start() { not_at_start_ = true; }
1044 void set_being_calculated(bool b) { being_calculated_ = b; } 1059 void set_being_calculated(bool b) { being_calculated_ = b; }
1045 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; } 1060 virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
1046 1061
1047 protected: 1062 protected:
1048 int GreedyLoopTextLength(GuardedAlternative* alternative); 1063 int GreedyLoopTextLength(GuardedAlternative* alternative);
1049 ZoneList<GuardedAlternative>* alternatives_; 1064 ZoneList<GuardedAlternative>* alternatives_;
1050 1065
1051 private: 1066 private:
1052 friend class DispatchTableConstructor; 1067 friend class DispatchTableConstructor;
1053 friend class Analysis; 1068 friend class Analysis;
1054 void GenerateGuard(RegExpMacroAssembler* macro_assembler, 1069 void GenerateGuard(RegExpMacroAssembler* macro_assembler,
1055 Guard* guard, 1070 Guard* guard,
1056 Trace* trace); 1071 Trace* trace);
1057 int CalculatePreloadCharacters(RegExpCompiler* compiler); 1072 int CalculatePreloadCharacters(RegExpCompiler* compiler, bool not_at_start);
1058 void EmitOutOfLineContinuation(RegExpCompiler* compiler, 1073 void EmitOutOfLineContinuation(RegExpCompiler* compiler,
1059 Trace* trace, 1074 Trace* trace,
1060 GuardedAlternative alternative, 1075 GuardedAlternative alternative,
1061 AlternativeGeneration* alt_gen, 1076 AlternativeGeneration* alt_gen,
1062 int preload_characters, 1077 int preload_characters,
1063 bool next_expects_preload); 1078 bool next_expects_preload);
1064 DispatchTable* table_; 1079 DispatchTable* table_;
1065 // If true, this node is never checked at the start of the input. 1080 // If true, this node is never checked at the start of the input.
1066 // Allows a new trace to start with at_start() set to false. 1081 // Allows a new trace to start with at_start() set to false.
1067 bool not_at_start_; 1082 bool not_at_start_;
1068 bool being_calculated_; 1083 bool being_calculated_;
1069 }; 1084 };
1070 1085
1071 1086
1072 class NegativeLookaheadChoiceNode: public ChoiceNode { 1087 class NegativeLookaheadChoiceNode: public ChoiceNode {
1073 public: 1088 public:
1074 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, 1089 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
1075 GuardedAlternative then_do_this) 1090 GuardedAlternative then_do_this)
1076 : ChoiceNode(2) { 1091 : ChoiceNode(2) {
1077 AddAlternative(this_must_fail); 1092 AddAlternative(this_must_fail);
1078 AddAlternative(then_do_this); 1093 AddAlternative(then_do_this);
1079 } 1094 }
1080 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 1095 virtual int EatsAtLeast(int still_to_find,
1096 int recursion_depth,
1097 bool not_at_start);
1081 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 1098 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1082 RegExpCompiler* compiler, 1099 RegExpCompiler* compiler,
1083 int characters_filled_in, 1100 int characters_filled_in,
1084 bool not_at_start); 1101 bool not_at_start);
1085 // For a negative lookahead we don't emit the quick check for the 1102 // For a negative lookahead we don't emit the quick check for the
1086 // alternative that is expected to fail. This is because quick check code 1103 // alternative that is expected to fail. This is because quick check code
1087 // starts by loading enough characters for the alternative that takes fewest 1104 // starts by loading enough characters for the alternative that takes fewest
1088 // characters, but on a negative lookahead the negative branch did not take 1105 // characters, but on a negative lookahead the negative branch did not take
1089 // part in that calculation (EatsAtLeast) so the assumptions don't hold. 1106 // part in that calculation (EatsAtLeast) so the assumptions don't hold.
1090 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } 1107 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
1091 virtual int ComputeFirstCharacterSet(int budget); 1108 virtual int ComputeFirstCharacterSet(int budget);
1092 }; 1109 };
1093 1110
1094 1111
1095 class LoopChoiceNode: public ChoiceNode { 1112 class LoopChoiceNode: public ChoiceNode {
1096 public: 1113 public:
1097 explicit LoopChoiceNode(bool body_can_be_zero_length) 1114 explicit LoopChoiceNode(bool body_can_be_zero_length)
1098 : ChoiceNode(2), 1115 : ChoiceNode(2),
1099 loop_node_(NULL), 1116 loop_node_(NULL),
1100 continue_node_(NULL), 1117 continue_node_(NULL),
1101 body_can_be_zero_length_(body_can_be_zero_length) { } 1118 body_can_be_zero_length_(body_can_be_zero_length) { }
1102 void AddLoopAlternative(GuardedAlternative alt); 1119 void AddLoopAlternative(GuardedAlternative alt);
1103 void AddContinueAlternative(GuardedAlternative alt); 1120 void AddContinueAlternative(GuardedAlternative alt);
1104 virtual void Emit(RegExpCompiler* compiler, Trace* trace); 1121 virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1105 virtual int EatsAtLeast(int still_to_find, int recursion_depth); 1122 virtual int EatsAtLeast(int still_to_find,
1123 int recursion_depth,
1124 bool not_at_start);
1106 virtual void GetQuickCheckDetails(QuickCheckDetails* details, 1125 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1107 RegExpCompiler* compiler, 1126 RegExpCompiler* compiler,
1108 int characters_filled_in, 1127 int characters_filled_in,
1109 bool not_at_start); 1128 bool not_at_start);
1110 virtual int ComputeFirstCharacterSet(int budget); 1129 virtual int ComputeFirstCharacterSet(int budget);
1111 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } 1130 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
1112 RegExpNode* loop_node() { return loop_node_; } 1131 RegExpNode* loop_node() { return loop_node_; }
1113 RegExpNode* continue_node() { return continue_node_; } 1132 RegExpNode* continue_node() { return continue_node_; }
1114 bool body_can_be_zero_length() { return body_can_be_zero_length_; } 1133 bool body_can_be_zero_length() { return body_can_be_zero_length_; }
1115 virtual void Accept(NodeVisitor* visitor); 1134 virtual void Accept(NodeVisitor* visitor);
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 int offsets_vector_length_; 1472 int offsets_vector_length_;
1454 static int static_offsets_vector_[kStaticOffsetsVectorSize]; 1473 static int static_offsets_vector_[kStaticOffsetsVectorSize];
1455 1474
1456 friend class ExternalReference; 1475 friend class ExternalReference;
1457 }; 1476 };
1458 1477
1459 1478
1460 } } // namespace v8::internal 1479 } } // namespace v8::internal
1461 1480
1462 #endif // V8_JSREGEXP_H_ 1481 #endif // V8_JSREGEXP_H_
OLDNEW
« no previous file with comments | « no previous file | src/jsregexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698