| 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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 value->set(kJscreNumberOfCapturesIndex, Smi::FromInt(number_of_captures)); | 453 value->set(kJscreNumberOfCapturesIndex, Smi::FromInt(number_of_captures)); |
| 454 value->set(kJscreInternalIndex, *internal); | 454 value->set(kJscreInternalIndex, *internal); |
| 455 Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value); | 455 Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value); |
| 456 | 456 |
| 457 return re; | 457 return re; |
| 458 } | 458 } |
| 459 | 459 |
| 460 | 460 |
| 461 Handle<Object> RegExpImpl::Re2kExecOnce(Handle<JSRegExp> regexp, | 461 Handle<Object> RegExpImpl::Re2kExecOnce(Handle<JSRegExp> regexp, |
| 462 int num_captures, | 462 int num_captures, |
| 463 Handle<String> subject, | 463 Handle<String> two_byte_subject, |
| 464 int previous_index, | 464 int previous_index, |
| 465 const uc16* two_byte_subject, | |
| 466 int* offsets_vector, | 465 int* offsets_vector, |
| 467 int offsets_vector_length) { | 466 int offsets_vector_length) { |
| 467 #ifdef DEBUG |
| 468 if (FLAG_trace_regexp_bytecodes) { |
| 469 String* pattern = regexp->Pattern(); |
| 470 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); |
| 471 PrintF("\n\nSubject string: '%s'\n\n", *(two_byte_subject->ToCString())); |
| 472 } |
| 473 #endif |
| 474 ASSERT(StringShape(*two_byte_subject).IsTwoByteRepresentation()); |
| 475 ASSERT(two_byte_subject->IsFlat(StringShape(*two_byte_subject))); |
| 468 bool rc; | 476 bool rc; |
| 469 { | 477 { |
| 470 for (int i = (num_captures + 1) * 2 - 1; i >= 0; i--) { | 478 for (int i = (num_captures + 1) * 2 - 1; i >= 0; i--) { |
| 471 offsets_vector[i] = -1; | 479 offsets_vector[i] = -1; |
| 472 } | 480 } |
| 473 | 481 |
| 474 AssertNoAllocation a; | 482 LOG(RegExpExecEvent(regexp, previous_index, two_byte_subject)); |
| 475 | |
| 476 LOG(RegExpExecEvent(regexp, previous_index, subject)); | |
| 477 | 483 |
| 478 Handle<ByteArray> byte_codes = Re2kCode(regexp); | 484 Handle<ByteArray> byte_codes = Re2kCode(regexp); |
| 479 | 485 |
| 480 rc = Re2kInterpreter::Match(byte_codes, | 486 rc = Re2kInterpreter::Match(byte_codes, |
| 481 subject, | 487 two_byte_subject, |
| 482 offsets_vector, | 488 offsets_vector, |
| 483 previous_index); | 489 previous_index); |
| 484 } | 490 } |
| 485 | 491 |
| 486 if (!rc) { | 492 if (!rc) { |
| 487 return Factory::null_value(); | 493 return Factory::null_value(); |
| 488 } | 494 } |
| 489 | 495 |
| 490 Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1)); | 496 Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1)); |
| 491 // The captures come in (start, end+1) pairs. | 497 // The captures come in (start, end+1) pairs. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 // Prepare space for the return values. | 604 // Prepare space for the return values. |
| 599 int number_of_registers = Re2kNumberOfRegisters(regexp); | 605 int number_of_registers = Re2kNumberOfRegisters(regexp); |
| 600 OffsetsVector offsets(number_of_registers); | 606 OffsetsVector offsets(number_of_registers); |
| 601 | 607 |
| 602 int num_captures = Re2kNumberOfCaptures(regexp); | 608 int num_captures = Re2kNumberOfCaptures(regexp); |
| 603 | 609 |
| 604 int previous_index = static_cast<int>(DoubleToInteger(index->Number())); | 610 int previous_index = static_cast<int>(DoubleToInteger(index->Number())); |
| 605 | 611 |
| 606 Handle<String> subject16 = CachedStringToTwoByte(subject); | 612 Handle<String> subject16 = CachedStringToTwoByte(subject); |
| 607 | 613 |
| 608 Handle<Object> result(Re2kExecOnce(regexp, | 614 Handle<Object> result( |
| 609 num_captures, | 615 Re2kExecOnce(regexp, |
| 610 subject, | 616 num_captures, |
| 611 previous_index, | 617 subject16, |
| 612 subject16->GetTwoByteData(), | 618 previous_index, |
| 613 offsets.vector(), | 619 offsets.vector(), |
| 614 offsets.length())); | 620 offsets.length())); |
| 615 return result; | 621 return result; |
| 616 } | 622 } |
| 617 | 623 |
| 618 | 624 |
| 619 Handle<Object> RegExpImpl::JscreExec(Handle<JSRegExp> regexp, | 625 Handle<Object> RegExpImpl::JscreExec(Handle<JSRegExp> regexp, |
| 620 Handle<String> subject, | 626 Handle<String> subject, |
| 621 Handle<Object> index) { | 627 Handle<Object> index) { |
| 622 ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE); | 628 ASSERT_EQ(regexp->TypeTag(), JSRegExp::JSCRE); |
| 623 if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) { | 629 if (regexp->DataAt(JSRegExp::kJscreDataIndex)->IsUndefined()) { |
| 624 Handle<Object> compile_result = JscreCompile(regexp); | 630 Handle<Object> compile_result = JscreCompile(regexp); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 Handle<String> subject16 = CachedStringToTwoByte(subject); | 670 Handle<String> subject16 = CachedStringToTwoByte(subject); |
| 665 | 671 |
| 666 do { | 672 do { |
| 667 if (previous_index > subject->length() || previous_index < 0) { | 673 if (previous_index > subject->length() || previous_index < 0) { |
| 668 // Per ECMA-262 15.10.6.2, if the previous index is greater than the | 674 // Per ECMA-262 15.10.6.2, if the previous index is greater than the |
| 669 // string length, there is no match. | 675 // string length, there is no match. |
| 670 matches = Factory::null_value(); | 676 matches = Factory::null_value(); |
| 671 } else { | 677 } else { |
| 672 matches = Re2kExecOnce(regexp, | 678 matches = Re2kExecOnce(regexp, |
| 673 Re2kNumberOfCaptures(regexp), | 679 Re2kNumberOfCaptures(regexp), |
| 674 subject, | 680 subject16, |
| 675 previous_index, | 681 previous_index, |
| 676 subject16->GetTwoByteData(), | |
| 677 offsets.vector(), | 682 offsets.vector(), |
| 678 offsets.length()); | 683 offsets.length()); |
| 679 | 684 |
| 680 if (matches->IsJSArray()) { | 685 if (matches->IsJSArray()) { |
| 681 SetElement(result, i, matches); | 686 SetElement(result, i, matches); |
| 682 i++; | 687 i++; |
| 683 previous_index = offsets.vector()[1]; | 688 previous_index = offsets.vector()[1]; |
| 684 if (offsets.vector()[0] == offsets.vector()[1]) { | 689 if (offsets.vector()[0] == offsets.vector()[1]) { |
| 685 previous_index++; | 690 previous_index++; |
| 686 } | 691 } |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } | 843 inline void AddWork(RegExpNode* node) { work_list_->Add(node); } |
| 839 | 844 |
| 840 static const int kImplementationOffset = 0; | 845 static const int kImplementationOffset = 0; |
| 841 static const int kNumberOfRegistersOffset = 0; | 846 static const int kNumberOfRegistersOffset = 0; |
| 842 static const int kCodeOffset = 1; | 847 static const int kCodeOffset = 1; |
| 843 | 848 |
| 844 RegExpMacroAssembler* macro_assembler() { return macro_assembler_; } | 849 RegExpMacroAssembler* macro_assembler() { return macro_assembler_; } |
| 845 EndNode* accept() { return accept_; } | 850 EndNode* accept() { return accept_; } |
| 846 EndNode* backtrack() { return backtrack_; } | 851 EndNode* backtrack() { return backtrack_; } |
| 847 | 852 |
| 853 static const int kMaxRecursion = 100; |
| 854 inline int recursion_depth() { return recursion_depth_; } |
| 855 inline void IncrementRecursionDepth() { recursion_depth_++; } |
| 856 inline void DecrementRecursionDepth() { recursion_depth_--; } |
| 857 |
| 848 private: | 858 private: |
| 849 EndNode* accept_; | 859 EndNode* accept_; |
| 850 EndNode* backtrack_; | 860 EndNode* backtrack_; |
| 851 int next_register_; | 861 int next_register_; |
| 852 List<RegExpNode*>* work_list_; | 862 List<RegExpNode*>* work_list_; |
| 863 int recursion_depth_; |
| 853 RegExpMacroAssembler* macro_assembler_; | 864 RegExpMacroAssembler* macro_assembler_; |
| 854 }; | 865 }; |
| 855 | 866 |
| 856 | 867 |
| 857 // Attempts to compile the regexp using a Regexp2000 code generator. Returns | 868 // Attempts to compile the regexp using a Regexp2000 code generator. Returns |
| 858 // a fixed array or a null handle depending on whether it succeeded. | 869 // a fixed array or a null handle depending on whether it succeeded. |
| 859 RegExpCompiler::RegExpCompiler(int capture_count) | 870 RegExpCompiler::RegExpCompiler(int capture_count) |
| 860 : next_register_(2 * capture_count), | 871 : next_register_(2 * (capture_count + 1)), |
| 861 work_list_(NULL) { | 872 work_list_(NULL), |
| 873 recursion_depth_(0) { |
| 862 accept_ = new EndNode(EndNode::ACCEPT); | 874 accept_ = new EndNode(EndNode::ACCEPT); |
| 863 backtrack_ = new EndNode(EndNode::BACKTRACK); | 875 backtrack_ = new EndNode(EndNode::BACKTRACK); |
| 864 } | 876 } |
| 865 | 877 |
| 866 | 878 |
| 867 Handle<FixedArray> RegExpCompiler::Assemble( | 879 Handle<FixedArray> RegExpCompiler::Assemble( |
| 868 RegExpMacroAssembler* macro_assembler, | 880 RegExpMacroAssembler* macro_assembler, |
| 869 RegExpNode* start, | 881 RegExpNode* start, |
| 870 int capture_count, | 882 int capture_count, |
| 871 bool case_independent) { | 883 bool case_independent) { |
| 872 if (case_independent) return Handle<FixedArray>::null(); | 884 if (case_independent) return Handle<FixedArray>::null(); |
| 873 macro_assembler_ = macro_assembler; | 885 macro_assembler_ = macro_assembler; |
| 874 List <RegExpNode*> work_list(0); | 886 List <RegExpNode*> work_list(0); |
| 875 work_list_ = &work_list; | 887 work_list_ = &work_list; |
| 876 Label fail; | 888 Label fail; |
| 877 macro_assembler->PushBacktrack(&fail); | 889 macro_assembler->PushBacktrack(&fail); |
| 878 if (!start->GoTo(this)) { | 890 if (!start->GoTo(this)) { |
| 879 fail.Unuse(); | 891 fail.Unuse(); |
| 880 return Handle<FixedArray>::null(); | 892 return Handle<FixedArray>::null(); |
| 881 } | 893 } |
| 882 while (!work_list.is_empty()) { | 894 while (!work_list.is_empty()) { |
| 883 if (!work_list.RemoveLast()->Emit(this)) { | 895 if (!work_list.RemoveLast()->GoTo(this)) { |
| 884 fail.Unuse(); | 896 fail.Unuse(); |
| 885 return Handle<FixedArray>::null(); | 897 return Handle<FixedArray>::null(); |
| 886 } | 898 } |
| 887 } | 899 } |
| 888 macro_assembler->Bind(&fail); | 900 macro_assembler->Bind(&fail); |
| 889 macro_assembler->Fail(); | 901 macro_assembler->Fail(); |
| 890 Handle<FixedArray> array = | 902 Handle<FixedArray> array = |
| 891 Factory::NewFixedArray(RegExpImpl::kRe2kDataLength); | 903 Factory::NewFixedArray(RegExpImpl::kRe2kDataLength); |
| 892 array->set(RegExpImpl::kRe2kImplementationIndex, | 904 array->set(RegExpImpl::kRe2kImplementationIndex, |
| 893 Smi::FromInt(macro_assembler->Implementation())); | 905 Smi::FromInt(macro_assembler->Implementation())); |
| 894 array->set(RegExpImpl::kRe2kNumberOfRegistersIndex, | 906 array->set(RegExpImpl::kRe2kNumberOfRegistersIndex, |
| 895 Smi::FromInt(next_register_)); | 907 Smi::FromInt(next_register_)); |
| 896 array->set(RegExpImpl::kRe2kNumberOfCapturesIndex, | 908 array->set(RegExpImpl::kRe2kNumberOfCapturesIndex, |
| 897 Smi::FromInt(capture_count)); | 909 Smi::FromInt(capture_count)); |
| 898 Handle<Object> code = macro_assembler->GetCode(); | 910 Handle<Object> code = macro_assembler->GetCode(); |
| 899 array->set(RegExpImpl::kRe2kCodeIndex, *code); | 911 array->set(RegExpImpl::kRe2kCodeIndex, *code); |
| 900 work_list_ = NULL; | 912 work_list_ = NULL; |
| 901 return array; | 913 return array; |
| 902 } | 914 } |
| 903 | 915 |
| 904 | 916 |
| 905 bool RegExpNode::GoTo(RegExpCompiler* compiler) { | 917 bool RegExpNode::GoTo(RegExpCompiler* compiler) { |
| 918 // TODO(erikcorry): Implement support. |
| 919 if (info_.follows_word_interest || |
| 920 info_.follows_newline_interest || |
| 921 info_.follows_start_interest) { |
| 922 return false; |
| 923 } |
| 906 if (label_.is_bound()) { | 924 if (label_.is_bound()) { |
| 907 compiler->macro_assembler()->GoTo(&label_); | 925 compiler->macro_assembler()->GoTo(&label_); |
| 908 return true; | 926 return true; |
| 909 } else { | 927 } else { |
| 910 return Emit(compiler); | 928 if (compiler->recursion_depth() > RegExpCompiler::kMaxRecursion) { |
| 929 compiler->macro_assembler()->GoTo(&label_); |
| 930 compiler->AddWork(this); |
| 931 return true; |
| 932 } else { |
| 933 compiler->IncrementRecursionDepth(); |
| 934 bool how_it_went = Emit(compiler); |
| 935 compiler->DecrementRecursionDepth(); |
| 936 return how_it_went; |
| 937 } |
| 911 } | 938 } |
| 912 } | 939 } |
| 913 | 940 |
| 914 | 941 |
| 942 bool EndNode::GoTo(RegExpCompiler* compiler) { |
| 943 if (info()->follows_word_interest || |
| 944 info()->follows_newline_interest || |
| 945 info()->follows_start_interest) { |
| 946 return false; |
| 947 } |
| 948 if (!label()->is_bound()) { |
| 949 Bind(compiler->macro_assembler()); |
| 950 } |
| 951 switch (action_) { |
| 952 case ACCEPT: |
| 953 compiler->macro_assembler()->Succeed(); |
| 954 break; |
| 955 case BACKTRACK: |
| 956 compiler->macro_assembler()->Backtrack(); |
| 957 break; |
| 958 } |
| 959 return true; |
| 960 } |
| 961 |
| 962 |
| 915 Label* RegExpNode::label() { | 963 Label* RegExpNode::label() { |
| 916 return &label_; | 964 return &label_; |
| 917 } | 965 } |
| 918 | 966 |
| 919 | 967 |
| 920 bool EndNode::Emit(RegExpCompiler* compiler) { | 968 bool EndNode::Emit(RegExpCompiler* compiler) { |
| 969 RegExpMacroAssembler* macro = compiler->macro_assembler(); |
| 921 switch (action_) { | 970 switch (action_) { |
| 922 case ACCEPT: | 971 case ACCEPT: |
| 923 compiler->macro_assembler()->Succeed(); | 972 Bind(macro); |
| 973 macro->Succeed(); |
| 924 return true; | 974 return true; |
| 925 case BACKTRACK: | 975 case BACKTRACK: |
| 926 compiler->macro_assembler()->Backtrack(); | 976 Bind(macro); |
| 977 macro->Backtrack(); |
| 927 return true; | 978 return true; |
| 928 } | 979 } |
| 929 return false; | 980 return false; |
| 930 } | 981 } |
| 931 | 982 |
| 932 | 983 |
| 933 void GuardedAlternative::AddGuard(Guard* guard) { | 984 void GuardedAlternative::AddGuard(Guard* guard) { |
| 934 if (guards_ == NULL) | 985 if (guards_ == NULL) |
| 935 guards_ = new ZoneList<Guard*>(1); | 986 guards_ = new ZoneList<Guard*>(1); |
| 936 guards_->Add(guard); | 987 guards_->Add(guard); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 visitor->Visit##Type(this); \ | 1039 visitor->Visit##Type(this); \ |
| 989 } | 1040 } |
| 990 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) | 1041 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) |
| 991 #undef DEFINE_ACCEPT | 1042 #undef DEFINE_ACCEPT |
| 992 | 1043 |
| 993 | 1044 |
| 994 // ------------------------------------------------------------------- | 1045 // ------------------------------------------------------------------- |
| 995 // Emit code. | 1046 // Emit code. |
| 996 | 1047 |
| 997 | 1048 |
| 998 void ChoiceNode::GenerateGuard(RegExpCompiler* compiler, | 1049 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, |
| 999 Guard *guard, | 1050 Guard* guard, |
| 1000 Label* on_failure) { | 1051 Label* on_failure) { |
| 1052 switch (guard->op()) { |
| 1053 case Guard::LT: |
| 1054 macro_assembler->IfRegisterGE(guard->reg(), guard->value(), on_failure); |
| 1055 break; |
| 1056 case Guard::GEQ: |
| 1057 macro_assembler->IfRegisterLT(guard->reg(), guard->value(), on_failure); |
| 1058 break; |
| 1059 } |
| 1060 } |
| 1061 |
| 1062 |
| 1063 bool TextNode::Emit(RegExpCompiler* compiler) { |
| 1064 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
| 1065 Bind(macro_assembler); |
| 1066 int element_count = elms_->length(); |
| 1067 int cp_offset = 0; |
| 1068 for (int i = 0; i < element_count; i++) { |
| 1069 TextElement elm = (*elms_)[i]; |
| 1070 switch (elm.type) { |
| 1071 case TextElement::ATOM: { |
| 1072 Vector<const uc16> quarks = elm.data.u_atom->data(); |
| 1073 macro_assembler->CheckCharacters(quarks, |
| 1074 cp_offset, |
| 1075 on_failure_->label()); |
| 1076 cp_offset += quarks.length(); |
| 1077 break; |
| 1078 } |
| 1079 case TextElement::CHAR_CLASS: { |
| 1080 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 1081 if (cc->is_negated()) return false; |
| 1082 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure_->label()); |
| 1083 cp_offset++; |
| 1084 |
| 1085 ZoneList<CharacterRange>* ranges = cc->ranges(); |
| 1086 |
| 1087 Label found; |
| 1088 |
| 1089 int range_count = ranges->length(); |
| 1090 |
| 1091 if (range_count == 0) { |
| 1092 on_failure()->GoTo(compiler); |
| 1093 break; |
| 1094 } |
| 1095 |
| 1096 for (int i = 0; i < range_count - 1; i++) { |
| 1097 CharacterRange& range = (*ranges)[i]; |
| 1098 Label next_range; |
| 1099 uc16 from = range.from(); |
| 1100 uc16 to = range.to(); |
| 1101 if (from != 0) { |
| 1102 macro_assembler->CheckCharacterLT(from, &next_range); |
| 1103 } |
| 1104 if (to != 0xffff) { |
| 1105 macro_assembler->CheckCharacterLT(to + 1, &found); |
| 1106 } else { |
| 1107 macro_assembler->AdvanceCurrentPosition(1); |
| 1108 on_success()->GoTo(compiler); |
| 1109 } |
| 1110 macro_assembler->Bind(&next_range); |
| 1111 } |
| 1112 |
| 1113 CharacterRange& range = (*ranges)[range_count - 1]; |
| 1114 uc16 from = range.from(); |
| 1115 uc16 to = range.to(); |
| 1116 if (from != 0) { |
| 1117 macro_assembler->CheckCharacterLT(from, on_failure_->label()); |
| 1118 } |
| 1119 if (to != 0xffff) { |
| 1120 macro_assembler->CheckCharacterGT(to, on_failure_->label()); |
| 1121 } |
| 1122 compiler->AddWork(on_failure_); |
| 1123 macro_assembler->Bind(&found); |
| 1124 break; |
| 1125 } |
| 1126 default: |
| 1127 UNREACHABLE(); |
| 1128 return false; |
| 1129 } |
| 1130 } |
| 1131 macro_assembler->AdvanceCurrentPosition(cp_offset); |
| 1132 return on_success()->GoTo(compiler); |
| 1001 } | 1133 } |
| 1002 | 1134 |
| 1003 | 1135 |
| 1004 bool ChoiceNode::Emit(RegExpCompiler* compiler) { | 1136 bool ChoiceNode::Emit(RegExpCompiler* compiler) { |
| 1005 int choice_count = alternatives_->length(); | 1137 int choice_count = alternatives_->length(); |
| 1006 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); | 1138 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); |
| 1139 Bind(macro_assembler); |
| 1007 // For now we just call all choices one after the other. The idea ultimately | 1140 // For now we just call all choices one after the other. The idea ultimately |
| 1008 // is to use the Dispatch table to try only the relevant ones. | 1141 // is to use the Dispatch table to try only the relevant ones. |
| 1009 for (int i = 0; i < choice_count; i++) { | 1142 int i; |
| 1143 for (i = 0; i < choice_count - 1; i++) { |
| 1010 GuardedAlternative alternative = (*alternatives_)[i]; | 1144 GuardedAlternative alternative = (*alternatives_)[i]; |
| 1011 Label after; | 1145 Label after; |
| 1012 Label* next_alternative; | 1146 Label after_no_pop_cp; |
| 1013 if (i < choice_count - 1) { | |
| 1014 next_alternative = &after; | |
| 1015 } else { | |
| 1016 next_alternative = on_failure_->label(); | |
| 1017 } | |
| 1018 ZoneList<Guard*>* guards = alternative.guards(); | 1147 ZoneList<Guard*>* guards = alternative.guards(); |
| 1019 if (guards != NULL) { | 1148 if (guards != NULL) { |
| 1020 int guard_count = guards->length(); | 1149 int guard_count = guards->length(); |
| 1021 for (int j = 0; j < guard_count; j++) { | 1150 for (int j = 0; j < guard_count; j++) { |
| 1022 GenerateGuard(compiler, (*guards)[i], next_alternative); | 1151 GenerateGuard(macro_assembler, (*guards)[j], &after_no_pop_cp); |
| 1023 } | 1152 } |
| 1024 } | 1153 } |
| 1025 macro_assembler->PushBacktrack(next_alternative); | 1154 macro_assembler->PushCurrentPosition(); |
| 1026 if (!alternative.node()->Emit(compiler)) { | 1155 macro_assembler->PushBacktrack(&after); |
| 1156 if (!alternative.node()->GoTo(compiler)) { |
| 1027 after.Unuse(); | 1157 after.Unuse(); |
| 1028 if (next_alternative != &after) { | 1158 after_no_pop_cp.Unuse(); |
| 1029 next_alternative->Unuse(); | |
| 1030 } | |
| 1031 return false; | 1159 return false; |
| 1032 } | 1160 } |
| 1033 if (i < choice_count - 1) { | 1161 macro_assembler->Bind(&after); |
| 1034 macro_assembler->Bind(&after); | 1162 macro_assembler->PopCurrentPosition(); |
| 1035 } else { | 1163 macro_assembler->Bind(&after_no_pop_cp); |
| 1036 after.Unuse(); | 1164 } |
| 1165 GuardedAlternative alternative = (*alternatives_)[i]; |
| 1166 ZoneList<Guard*>* guards = alternative.guards(); |
| 1167 if (guards != NULL) { |
| 1168 int guard_count = guards->length(); |
| 1169 for (int j = 0; j < guard_count; j++) { |
| 1170 GenerateGuard(macro_assembler, (*guards)[j], on_failure_->label()); |
| 1037 } | 1171 } |
| 1038 } | 1172 } |
| 1173 if (!on_failure_->IsBacktrack()) { |
| 1174 macro_assembler->PushBacktrack(on_failure_->label()); |
| 1175 } |
| 1176 if (!alternative.node()->GoTo(compiler)) { |
| 1177 return false; |
| 1178 } |
| 1039 compiler->AddWork(on_failure_); | 1179 compiler->AddWork(on_failure_); |
| 1040 return true; | 1180 return true; |
| 1041 } | 1181 } |
| 1042 | 1182 |
| 1043 | 1183 |
| 1044 bool ActionNode::Emit(RegExpCompiler* compiler) { | 1184 bool ActionNode::Emit(RegExpCompiler* compiler) { |
| 1045 RegExpMacroAssembler* macro = compiler->macro_assembler(); | 1185 RegExpMacroAssembler* macro = compiler->macro_assembler(); |
| 1186 Bind(macro); |
| 1046 switch (type_) { | 1187 switch (type_) { |
| 1047 case STORE_REGISTER: | 1188 case STORE_REGISTER: |
| 1048 macro->SetRegister(data_.u_store_register.reg, | 1189 macro->SetRegister(data_.u_store_register.reg, |
| 1049 data_.u_store_register.value); | 1190 data_.u_store_register.value); |
| 1050 break; | 1191 break; |
| 1051 case INCREMENT_REGISTER: | 1192 case INCREMENT_REGISTER: { |
| 1193 Label undo; |
| 1194 macro->PushBacktrack(&undo); |
| 1052 macro->AdvanceRegister(data_.u_increment_register.reg, 1); | 1195 macro->AdvanceRegister(data_.u_increment_register.reg, 1); |
| 1196 bool ok = on_success()->GoTo(compiler); |
| 1197 if (!ok) { |
| 1198 undo.Unuse(); |
| 1199 return false; |
| 1200 } |
| 1201 macro->Bind(&undo); |
| 1202 macro->AdvanceRegister(data_.u_increment_register.reg, -1); |
| 1203 macro->Backtrack(); |
| 1053 break; | 1204 break; |
| 1054 case STORE_POSITION: | 1205 } |
| 1055 macro->PushCurrentPosition(); | 1206 case STORE_POSITION: { |
| 1207 Label undo; |
| 1208 macro->PushRegister(data_.u_position_register.reg); |
| 1209 macro->PushBacktrack(&undo); |
| 1210 macro->WriteCurrentPositionToRegister(data_.u_position_register.reg); |
| 1211 bool ok = on_success()->GoTo(compiler); |
| 1212 if (!ok) { |
| 1213 undo.Unuse(); |
| 1214 return false; |
| 1215 } |
| 1216 macro->Bind(&undo); |
| 1217 macro->PopRegister(data_.u_position_register.reg); |
| 1218 macro->Backtrack(); |
| 1056 break; | 1219 break; |
| 1220 } |
| 1057 case RESTORE_POSITION: | 1221 case RESTORE_POSITION: |
| 1058 macro->PopCurrentPosition(); | 1222 // TODO(erikcorry): Implement this. |
| 1059 break; | 1223 return false; |
| 1060 case BEGIN_SUBMATCH: | 1224 case BEGIN_SUBMATCH: |
| 1061 // TODO(erikcorry): Implement this. | 1225 // TODO(erikcorry): Implement this. |
| 1062 return false; | 1226 return false; |
| 1063 case ESCAPE_SUBMATCH: | 1227 case ESCAPE_SUBMATCH: |
| 1064 // TODO(erikcorry): Implement this. | 1228 // TODO(erikcorry): Implement this. |
| 1065 return false; | 1229 return false; |
| 1066 case END_SUBMATCH: | 1230 case END_SUBMATCH: |
| 1067 // TODO(erikcorry): Implement this. | 1231 // TODO(erikcorry): Implement this. |
| 1068 return false; | 1232 return false; |
| 1069 default: | 1233 default: |
| 1070 UNREACHABLE(); | 1234 UNREACHABLE(); |
| 1071 return false; | 1235 return false; |
| 1072 } | 1236 } |
| 1073 compiler->AddWork(on_success()); | 1237 return on_success()->GoTo(compiler); |
| 1074 return true; | |
| 1075 } | 1238 } |
| 1076 | 1239 |
| 1077 | 1240 |
| 1078 // ------------------------------------------------------------------- | 1241 // ------------------------------------------------------------------- |
| 1079 // Dot/dotty output | 1242 // Dot/dotty output |
| 1080 | 1243 |
| 1081 | 1244 |
| 1082 #ifdef DEBUG | 1245 #ifdef DEBUG |
| 1083 | 1246 |
| 1084 | 1247 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1558 RegExpNode* current = on_success; | 1721 RegExpNode* current = on_success; |
| 1559 for (int i = children->length() - 1; i >= 0; i--) { | 1722 for (int i = children->length() - 1; i >= 0; i--) { |
| 1560 current = children->at(i)->ToNode(compiler, current, on_failure); | 1723 current = children->at(i)->ToNode(compiler, current, on_failure); |
| 1561 } | 1724 } |
| 1562 return current; | 1725 return current; |
| 1563 } | 1726 } |
| 1564 | 1727 |
| 1565 | 1728 |
| 1566 static const int kSpaceRangeCount = 20; | 1729 static const int kSpaceRangeCount = 20; |
| 1567 static const uc16 kSpaceRanges[kSpaceRangeCount] = { | 1730 static const uc16 kSpaceRanges[kSpaceRangeCount] = { |
| 1568 0x0009, 0x0009, 0x000B, 0x000C, 0x0020, 0x0020, 0x00A0, 0x00A0, | 1731 0x0009, 0x000D, 0x0020, 0x0020, 0x00A0, 0x00A0, 0x1680, |
| 1569 0x1680, 0x1680, 0x180E, 0x180E, 0x2000, 0x200A, 0x202F, 0x202F, | 1732 0x1680, 0x180E, 0x180E, 0x2000, 0x200A, 0x2028, 0x2029, |
| 1570 0x205F, 0x205F, 0x3000, 0x3000 | 1733 0x202F, 0x202F, 0x205F, 0x205F, 0x3000, 0x3000 |
| 1571 }; | 1734 }; |
| 1572 | 1735 |
| 1573 | 1736 |
| 1574 static const int kWordRangeCount = 8; | 1737 static const int kWordRangeCount = 8; |
| 1575 static const uc16 kWordRanges[kWordRangeCount] = { | 1738 static const uc16 kWordRanges[kWordRangeCount] = { |
| 1576 '0', '9', 'A', 'Z', '_', '_', 'a', 'z' | 1739 '0', '9', 'A', 'Z', '_', '_', 'a', 'z' |
| 1577 }; | 1740 }; |
| 1578 | 1741 |
| 1579 | 1742 |
| 1580 static const int kDigitRangeCount = 2; | 1743 static const int kDigitRangeCount = 2; |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1962 DispatchTableConstructor constructor(node->table()); | 2125 DispatchTableConstructor constructor(node->table()); |
| 1963 constructor.BuildTable(node); | 2126 constructor.BuildTable(node); |
| 1964 } | 2127 } |
| 1965 ASSERT(node->table_calculated()); | 2128 ASSERT(node->table_calculated()); |
| 1966 AddDispatchRange adder(this); | 2129 AddDispatchRange adder(this); |
| 1967 node->table()->ForEach(&adder); | 2130 node->table()->ForEach(&adder); |
| 1968 } | 2131 } |
| 1969 | 2132 |
| 1970 | 2133 |
| 1971 void DispatchTableConstructor::VisitBackreference(BackreferenceNode* that) { | 2134 void DispatchTableConstructor::VisitBackreference(BackreferenceNode* that) { |
| 1972 UNIMPLEMENTED(); | 2135 // TODO(plesner): What should this do? |
| 1973 } | 2136 } |
| 1974 | 2137 |
| 1975 | 2138 |
| 1976 | 2139 |
| 1977 static int CompareRangeByFrom(const CharacterRange* a, | 2140 static int CompareRangeByFrom(const CharacterRange* a, |
| 1978 const CharacterRange* b) { | 2141 const CharacterRange* b) { |
| 1979 return Spaceship<uc16>(a->from(), b->from()); | 2142 return Spaceship<uc16>(a->from(), b->from()); |
| 1980 } | 2143 } |
| 1981 | 2144 |
| 1982 | 2145 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2048 RegExpNode* node = RegExpQuantifier::ToNode(0, | 2211 RegExpNode* node = RegExpQuantifier::ToNode(0, |
| 2049 RegExpQuantifier::kInfinity, | 2212 RegExpQuantifier::kInfinity, |
| 2050 false, | 2213 false, |
| 2051 new RegExpCharacterClass('.'), | 2214 new RegExpCharacterClass('.'), |
| 2052 &compiler, | 2215 &compiler, |
| 2053 captured_body, | 2216 captured_body, |
| 2054 compiler.backtrack()); | 2217 compiler.backtrack()); |
| 2055 if (node_return != NULL) *node_return = node; | 2218 if (node_return != NULL) *node_return = node; |
| 2056 Analysis analysis; | 2219 Analysis analysis; |
| 2057 analysis.EnsureAnalyzed(node); | 2220 analysis.EnsureAnalyzed(node); |
| 2058 byte codes[10240]; | 2221 byte codes[1024]; |
| 2059 Re2kAssembler assembler(Vector<byte>(codes, 1024)); | 2222 Re2kAssembler assembler(Vector<byte>(codes, 1024)); |
| 2060 RegExpMacroAssemblerRe2k macro_assembler(&assembler); | 2223 RegExpMacroAssemblerRe2k macro_assembler(&assembler); |
| 2061 return compiler.Assemble(¯o_assembler, | 2224 return compiler.Assemble(¯o_assembler, |
| 2062 node, | 2225 node, |
| 2063 input->capture_count, | 2226 input->capture_count, |
| 2064 ignore_case); | 2227 ignore_case); |
| 2065 } | 2228 } |
| 2066 | 2229 |
| 2067 RegExpMacroAssembler::RegExpMacroAssembler() { | 2230 RegExpMacroAssembler::RegExpMacroAssembler() { |
| 2068 } | 2231 } |
| 2069 | 2232 |
| 2070 RegExpMacroAssembler::~RegExpMacroAssembler() { | 2233 RegExpMacroAssembler::~RegExpMacroAssembler() { |
| 2071 } | 2234 } |
| 2072 | 2235 |
| 2073 | 2236 |
| 2074 }} // namespace v8::internal | 2237 }} // namespace v8::internal |
| OLD | NEW |