OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2500 FixedArrayBuilder array_builder_; | 2500 FixedArrayBuilder array_builder_; |
2501 Handle<String> subject_; | 2501 Handle<String> subject_; |
2502 int character_count_; | 2502 int character_count_; |
2503 bool is_ascii_; | 2503 bool is_ascii_; |
2504 }; | 2504 }; |
2505 | 2505 |
2506 | 2506 |
2507 class CompiledReplacement { | 2507 class CompiledReplacement { |
2508 public: | 2508 public: |
2509 CompiledReplacement() | 2509 CompiledReplacement() |
2510 : parts_(1), replacement_substrings_(0) {} | 2510 : parts_(1), replacement_substrings_(0), simple_hint(false) {} |
2511 | 2511 |
2512 void Compile(Handle<String> replacement, | 2512 void Compile(Handle<String> replacement, |
2513 int capture_count, | 2513 int capture_count, |
2514 int subject_length); | 2514 int subject_length); |
2515 | 2515 |
2516 void Apply(ReplacementStringBuilder* builder, | 2516 void Apply(ReplacementStringBuilder* builder, |
2517 int match_from, | 2517 int match_from, |
2518 int match_to, | 2518 int match_to, |
2519 Handle<JSArray> last_match_info); | 2519 Handle<JSArray> last_match_info); |
2520 | 2520 |
2521 // Number of distinct parts of the replacement pattern. | 2521 // Number of distinct parts of the replacement pattern. |
2522 int parts() { | 2522 int parts() { |
2523 return parts_.length(); | 2523 return parts_.length(); |
2524 } | 2524 } |
2525 | 2525 |
2526 int IsSimple() { | |
Jakob Kummerow
2011/09/07 16:11:24
nit 1: This is C++. We have bools.
nit 2: A simple
| |
2527 return simple_hint; | |
2528 } | |
2529 | |
2526 private: | 2530 private: |
2527 enum PartType { | 2531 enum PartType { |
2528 SUBJECT_PREFIX = 1, | 2532 SUBJECT_PREFIX = 1, |
2529 SUBJECT_SUFFIX, | 2533 SUBJECT_SUFFIX, |
2530 SUBJECT_CAPTURE, | 2534 SUBJECT_CAPTURE, |
2531 REPLACEMENT_SUBSTRING, | 2535 REPLACEMENT_SUBSTRING, |
2532 REPLACEMENT_STRING, | 2536 REPLACEMENT_STRING, |
2533 | 2537 |
2534 NUMBER_OF_PART_TYPES | 2538 NUMBER_OF_PART_TYPES |
2535 }; | 2539 }; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2571 // tag == SUBJECT_SUFFIX: data is unused. | 2575 // tag == SUBJECT_SUFFIX: data is unused. |
2572 // tag == SUBJECT_CAPTURE: data is the number of the capture. | 2576 // tag == SUBJECT_CAPTURE: data is the number of the capture. |
2573 // tag == REPLACEMENT_SUBSTRING || | 2577 // tag == REPLACEMENT_SUBSTRING || |
2574 // tag == REPLACEMENT_STRING: data is index into array of substrings | 2578 // tag == REPLACEMENT_STRING: data is index into array of substrings |
2575 // of the replacement string. | 2579 // of the replacement string. |
2576 // tag <= 0: Temporary representation of the substring of the replacement | 2580 // tag <= 0: Temporary representation of the substring of the replacement |
2577 // string ranging over -tag .. data. | 2581 // string ranging over -tag .. data. |
2578 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the | 2582 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the |
2579 // substring objects. | 2583 // substring objects. |
2580 int data; | 2584 int data; |
2585 | |
2581 }; | 2586 }; |
2582 | 2587 |
2583 template<typename Char> | 2588 template<typename Char> |
2584 static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts, | 2589 static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts, |
2585 Vector<Char> characters, | 2590 Vector<Char> characters, |
2586 int capture_count, | 2591 int capture_count, |
2587 int subject_length) { | 2592 int subject_length) { |
2588 int length = characters.length(); | 2593 int length = characters.length(); |
2589 int last = 0; | 2594 int last = 0; |
2595 bool simple = true; | |
2590 for (int i = 0; i < length; i++) { | 2596 for (int i = 0; i < length; i++) { |
2591 Char c = characters[i]; | 2597 Char c = characters[i]; |
2592 if (c == '$') { | 2598 if (c == '$') { |
2599 simple = false; | |
2593 int next_index = i + 1; | 2600 int next_index = i + 1; |
2594 if (next_index == length) { // No next character! | 2601 if (next_index == length) { // No next character! |
2595 break; | 2602 break; |
2596 } | 2603 } |
2597 Char c2 = characters[next_index]; | 2604 Char c2 = characters[next_index]; |
2598 switch (c2) { | 2605 switch (c2) { |
2599 case '$': | 2606 case '$': |
2600 if (i > last) { | 2607 if (i > last) { |
2601 // There is a substring before. Include the first "$". | 2608 // There is a substring before. Include the first "$". |
2602 parts->Add(ReplacementPart::ReplacementSubString(last, next_index)); | 2609 parts->Add(ReplacementPart::ReplacementSubString(last, next_index)); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2675 } | 2682 } |
2676 } | 2683 } |
2677 } | 2684 } |
2678 if (length > last) { | 2685 if (length > last) { |
2679 if (last == 0) { | 2686 if (last == 0) { |
2680 parts->Add(ReplacementPart::ReplacementString()); | 2687 parts->Add(ReplacementPart::ReplacementString()); |
2681 } else { | 2688 } else { |
2682 parts->Add(ReplacementPart::ReplacementSubString(last, length)); | 2689 parts->Add(ReplacementPart::ReplacementSubString(last, length)); |
2683 } | 2690 } |
2684 } | 2691 } |
2692 return simple; | |
2685 } | 2693 } |
2686 | 2694 |
2687 ZoneList<ReplacementPart> parts_; | 2695 ZoneList<ReplacementPart> parts_; |
2688 ZoneList<Handle<String> > replacement_substrings_; | 2696 ZoneList<Handle<String> > replacement_substrings_; |
2697 bool simple_hint; | |
Jakob Kummerow
2011/09/07 16:11:24
nit: trailing underscore please
| |
2689 }; | 2698 }; |
2690 | 2699 |
2691 | 2700 |
2692 void CompiledReplacement::Compile(Handle<String> replacement, | 2701 void CompiledReplacement::Compile(Handle<String> replacement, |
2693 int capture_count, | 2702 int capture_count, |
2694 int subject_length) { | 2703 int subject_length) { |
2695 { | 2704 { |
2696 AssertNoAllocation no_alloc; | 2705 AssertNoAllocation no_alloc; |
2697 String::FlatContent content = replacement->GetFlatContent(); | 2706 String::FlatContent content = replacement->GetFlatContent(); |
2698 ASSERT(content.IsFlat()); | 2707 ASSERT(content.IsFlat()); |
2699 if (content.IsAscii()) { | 2708 if (content.IsAscii()) { |
2700 ParseReplacementPattern(&parts_, | 2709 simple_hint = ParseReplacementPattern(&parts_, |
2701 content.ToAsciiVector(), | 2710 content.ToAsciiVector(), |
2702 capture_count, | 2711 capture_count, |
2703 subject_length); | 2712 subject_length); |
2704 } else { | 2713 } else { |
2705 ASSERT(content.IsTwoByte()); | 2714 ASSERT(content.IsTwoByte()); |
2706 ParseReplacementPattern(&parts_, | 2715 simple_hint = ParseReplacementPattern(&parts_, |
2707 content.ToUC16Vector(), | 2716 content.ToUC16Vector(), |
2708 capture_count, | 2717 capture_count, |
2709 subject_length); | 2718 subject_length); |
2710 } | 2719 } |
2711 } | 2720 } |
2712 Isolate* isolate = replacement->GetIsolate(); | 2721 Isolate* isolate = replacement->GetIsolate(); |
2713 // Find substrings of replacement string and create them as String objects. | 2722 // Find substrings of replacement string and create them as String objects. |
2714 int substring_index = 0; | 2723 int substring_index = 0; |
2715 for (int i = 0, n = parts_.length(); i < n; i++) { | 2724 for (int i = 0, n = parts_.length(); i < n; i++) { |
2716 int tag = parts_[i].tag; | 2725 int tag = parts_[i].tag; |
2717 if (tag <= 0) { // A replacement string slice. | 2726 if (tag <= 0) { // A replacement string slice. |
2718 int from = -tag; | 2727 int from = -tag; |
2719 int to = parts_[i].data; | 2728 int to = parts_[i].data; |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2894 | 2903 |
2895 Handle<ResultSeqString> result; | 2904 Handle<ResultSeqString> result; |
2896 if (ResultSeqString::kHasAsciiEncoding) { | 2905 if (ResultSeqString::kHasAsciiEncoding) { |
2897 result = Handle<ResultSeqString>::cast( | 2906 result = Handle<ResultSeqString>::cast( |
2898 isolate->factory()->NewRawAsciiString(result_len)); | 2907 isolate->factory()->NewRawAsciiString(result_len)); |
2899 } else { | 2908 } else { |
2900 result = Handle<ResultSeqString>::cast( | 2909 result = Handle<ResultSeqString>::cast( |
2901 isolate->factory()->NewRawTwoByteString(result_len)); | 2910 isolate->factory()->NewRawTwoByteString(result_len)); |
2902 } | 2911 } |
2903 | 2912 |
2904 for(int i = 0; i < matches; i++) { | 2913 for (int i = 0; i < matches; i++) { |
2905 // Copy non-matched subject content. | 2914 // Copy non-matched subject content. |
2906 String::WriteToFlat(*subject, | 2915 String::WriteToFlat(*subject, |
2907 result->GetChars() + result_pos, | 2916 result->GetChars() + result_pos, |
2908 subject_pos, | 2917 subject_pos, |
2909 indices.at(i)); | 2918 indices.at(i)); |
2910 result_pos += indices.at(i) - subject_pos; | 2919 result_pos += indices.at(i) - subject_pos; |
2911 // Replace match. | 2920 // Replace match. |
2912 | 2921 |
2913 if (replacement_len > 0) { | 2922 if (replacement_len > 0) { |
2914 String::WriteToFlat(*replacement, | 2923 String::WriteToFlat(*replacement, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2962 CompiledReplacement compiled_replacement; | 2971 CompiledReplacement compiled_replacement; |
2963 compiled_replacement.Compile(replacement_handle, | 2972 compiled_replacement.Compile(replacement_handle, |
2964 capture_count, | 2973 capture_count, |
2965 length); | 2974 length); |
2966 | 2975 |
2967 bool is_global = regexp_handle->GetFlags().is_global(); | 2976 bool is_global = regexp_handle->GetFlags().is_global(); |
2968 | 2977 |
2969 // Shortcut for simple non-regexp global replacements | 2978 // Shortcut for simple non-regexp global replacements |
2970 if (is_global && | 2979 if (is_global && |
2971 regexp->TypeTag() == JSRegExp::ATOM && | 2980 regexp->TypeTag() == JSRegExp::ATOM && |
2972 compiled_replacement.parts() == 1) { | 2981 compiled_replacement.IsSimple()) { |
2973 if (subject_handle->HasOnlyAsciiChars() && | 2982 if (subject_handle->HasOnlyAsciiChars() && |
2974 replacement_handle->HasOnlyAsciiChars()) { | 2983 replacement_handle->HasOnlyAsciiChars()) { |
2975 return StringReplaceStringWithString<SeqAsciiString>( | 2984 return StringReplaceStringWithString<SeqAsciiString>( |
2976 isolate, subject_handle, regexp_handle, replacement_handle); | 2985 isolate, subject_handle, regexp_handle, replacement_handle); |
2977 } else { | 2986 } else { |
2978 return StringReplaceStringWithString<SeqTwoByteString>( | 2987 return StringReplaceStringWithString<SeqTwoByteString>( |
2979 isolate, subject_handle, regexp_handle, replacement_handle); | 2988 isolate, subject_handle, regexp_handle, replacement_handle); |
2980 } | 2989 } |
2981 } | 2990 } |
2982 | 2991 |
(...skipping 10135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13118 } else { | 13127 } else { |
13119 // Handle last resort GC and make sure to allow future allocations | 13128 // Handle last resort GC and make sure to allow future allocations |
13120 // to grow the heap without causing GCs (if possible). | 13129 // to grow the heap without causing GCs (if possible). |
13121 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13130 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13122 isolate->heap()->CollectAllGarbage(false); | 13131 isolate->heap()->CollectAllGarbage(false); |
13123 } | 13132 } |
13124 } | 13133 } |
13125 | 13134 |
13126 | 13135 |
13127 } } // namespace v8::internal | 13136 } } // namespace v8::internal |
OLD | NEW |