| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 29 matching lines...) Expand all Loading... |
| 40 #include "execution.h" | 40 #include "execution.h" |
| 41 #include "jsregexp.h" | 41 #include "jsregexp.h" |
| 42 #include "liveedit.h" | 42 #include "liveedit.h" |
| 43 #include "parser.h" | 43 #include "parser.h" |
| 44 #include "platform.h" | 44 #include "platform.h" |
| 45 #include "runtime.h" | 45 #include "runtime.h" |
| 46 #include "scopeinfo.h" | 46 #include "scopeinfo.h" |
| 47 #include "smart-pointer.h" | 47 #include "smart-pointer.h" |
| 48 #include "stub-cache.h" | 48 #include "stub-cache.h" |
| 49 #include "v8threads.h" | 49 #include "v8threads.h" |
| 50 #include "string-search.h" |
| 50 | 51 |
| 51 namespace v8 { | 52 namespace v8 { |
| 52 namespace internal { | 53 namespace internal { |
| 53 | 54 |
| 54 | 55 |
| 55 #define RUNTIME_ASSERT(value) \ | 56 #define RUNTIME_ASSERT(value) \ |
| 56 if (!(value)) return Top::ThrowIllegalOperation(); | 57 if (!(value)) return Top::ThrowIllegalOperation(); |
| 57 | 58 |
| 58 // Cast the given object to a value of the specified type and store | 59 // Cast the given object to a value of the specified type and store |
| 59 // it in a variable with the given name. If the object is not of the | 60 // it in a variable with the given name. If the object is not of the |
| (...skipping 2504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2564 } | 2565 } |
| 2565 } | 2566 } |
| 2566 | 2567 |
| 2567 return StringReplaceRegExpWithString(subject, | 2568 return StringReplaceRegExpWithString(subject, |
| 2568 regexp, | 2569 regexp, |
| 2569 replacement, | 2570 replacement, |
| 2570 last_match_info); | 2571 last_match_info); |
| 2571 } | 2572 } |
| 2572 | 2573 |
| 2573 | 2574 |
| 2574 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a | |
| 2575 // limit, we can fix the size of tables. | |
| 2576 static const int kBMMaxShift = 0xff; | |
| 2577 // Reduce alphabet to this size. | |
| 2578 static const int kBMAlphabetSize = 0x100; | |
| 2579 // For patterns below this length, the skip length of Boyer-Moore is too short | |
| 2580 // to compensate for the algorithmic overhead compared to simple brute force. | |
| 2581 static const int kBMMinPatternLength = 7; | |
| 2582 | |
| 2583 // Holds the two buffers used by Boyer-Moore string search's Good Suffix | |
| 2584 // shift. Only allows the last kBMMaxShift characters of the needle | |
| 2585 // to be indexed. | |
| 2586 class BMGoodSuffixBuffers { | |
| 2587 public: | |
| 2588 BMGoodSuffixBuffers() {} | |
| 2589 inline void init(int needle_length) { | |
| 2590 ASSERT(needle_length > 1); | |
| 2591 int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift; | |
| 2592 int len = needle_length - start; | |
| 2593 biased_suffixes_ = suffixes_ - start; | |
| 2594 biased_good_suffix_shift_ = good_suffix_shift_ - start; | |
| 2595 for (int i = 0; i <= len; i++) { | |
| 2596 good_suffix_shift_[i] = len; | |
| 2597 } | |
| 2598 } | |
| 2599 inline int& suffix(int index) { | |
| 2600 ASSERT(biased_suffixes_ + index >= suffixes_); | |
| 2601 return biased_suffixes_[index]; | |
| 2602 } | |
| 2603 inline int& shift(int index) { | |
| 2604 ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_); | |
| 2605 return biased_good_suffix_shift_[index]; | |
| 2606 } | |
| 2607 private: | |
| 2608 int suffixes_[kBMMaxShift + 1]; | |
| 2609 int good_suffix_shift_[kBMMaxShift + 1]; | |
| 2610 int* biased_suffixes_; | |
| 2611 int* biased_good_suffix_shift_; | |
| 2612 DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers); | |
| 2613 }; | |
| 2614 | |
| 2615 // buffers reused by BoyerMoore | |
| 2616 static int bad_char_occurrence[kBMAlphabetSize]; | |
| 2617 static BMGoodSuffixBuffers bmgs_buffers; | |
| 2618 | |
| 2619 // State of the string match tables. | |
| 2620 // SIMPLE: No usable content in the buffers. | |
| 2621 // BOYER_MOORE_HORSPOOL: The bad_char_occurences table has been populated. | |
| 2622 // BOYER_MOORE: The bmgs_buffers tables have also been populated. | |
| 2623 // Whenever starting with a new needle, one should call InitializeStringSearch | |
| 2624 // to determine which search strategy to use, and in the case of a long-needle | |
| 2625 // strategy, the call also initializes the algorithm to SIMPLE. | |
| 2626 enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE }; | |
| 2627 static StringSearchAlgorithm algorithm; | |
| 2628 | |
| 2629 | |
| 2630 // Compute the bad-char table for Boyer-Moore in the static buffer. | |
| 2631 template <typename pchar> | |
| 2632 static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern) { | |
| 2633 // Only preprocess at most kBMMaxShift last characters of pattern. | |
| 2634 int start = pattern.length() < kBMMaxShift ? 0 | |
| 2635 : pattern.length() - kBMMaxShift; | |
| 2636 // Run forwards to populate bad_char_table, so that *last* instance | |
| 2637 // of character equivalence class is the one registered. | |
| 2638 // Notice: Doesn't include the last character. | |
| 2639 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1 | |
| 2640 : kBMAlphabetSize; | |
| 2641 if (start == 0) { // All patterns less than kBMMaxShift in length. | |
| 2642 memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence)); | |
| 2643 } else { | |
| 2644 for (int i = 0; i < table_size; i++) { | |
| 2645 bad_char_occurrence[i] = start - 1; | |
| 2646 } | |
| 2647 } | |
| 2648 for (int i = start; i < pattern.length() - 1; i++) { | |
| 2649 pchar c = pattern[i]; | |
| 2650 int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize; | |
| 2651 bad_char_occurrence[bucket] = i; | |
| 2652 } | |
| 2653 } | |
| 2654 | |
| 2655 | |
| 2656 template <typename pchar> | |
| 2657 static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern) { | |
| 2658 int m = pattern.length(); | |
| 2659 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift; | |
| 2660 int len = m - start; | |
| 2661 // Compute Good Suffix tables. | |
| 2662 bmgs_buffers.init(m); | |
| 2663 | |
| 2664 bmgs_buffers.shift(m-1) = 1; | |
| 2665 bmgs_buffers.suffix(m) = m + 1; | |
| 2666 pchar last_char = pattern[m - 1]; | |
| 2667 int suffix = m + 1; | |
| 2668 for (int i = m; i > start;) { | |
| 2669 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) { | |
| 2670 if (bmgs_buffers.shift(suffix) == len) { | |
| 2671 bmgs_buffers.shift(suffix) = suffix - i; | |
| 2672 } | |
| 2673 suffix = bmgs_buffers.suffix(suffix); | |
| 2674 } | |
| 2675 i--; | |
| 2676 suffix--; | |
| 2677 bmgs_buffers.suffix(i) = suffix; | |
| 2678 if (suffix == m) { | |
| 2679 // No suffix to extend, so we check against last_char only. | |
| 2680 while (i > start && pattern[i - 1] != last_char) { | |
| 2681 if (bmgs_buffers.shift(m) == len) { | |
| 2682 bmgs_buffers.shift(m) = m - i; | |
| 2683 } | |
| 2684 i--; | |
| 2685 bmgs_buffers.suffix(i) = m; | |
| 2686 } | |
| 2687 if (i > start) { | |
| 2688 i--; | |
| 2689 suffix--; | |
| 2690 bmgs_buffers.suffix(i) = suffix; | |
| 2691 } | |
| 2692 } | |
| 2693 } | |
| 2694 if (suffix < m) { | |
| 2695 for (int i = start; i <= m; i++) { | |
| 2696 if (bmgs_buffers.shift(i) == len) { | |
| 2697 bmgs_buffers.shift(i) = suffix - start; | |
| 2698 } | |
| 2699 if (i == suffix) { | |
| 2700 suffix = bmgs_buffers.suffix(suffix); | |
| 2701 } | |
| 2702 } | |
| 2703 } | |
| 2704 } | |
| 2705 | |
| 2706 | |
| 2707 template <typename schar, typename pchar> | |
| 2708 static inline int CharOccurrence(int char_code) { | |
| 2709 if (sizeof(schar) == 1) { | |
| 2710 return bad_char_occurrence[char_code]; | |
| 2711 } | |
| 2712 if (sizeof(pchar) == 1) { | |
| 2713 if (char_code > String::kMaxAsciiCharCode) { | |
| 2714 return -1; | |
| 2715 } | |
| 2716 return bad_char_occurrence[char_code]; | |
| 2717 } | |
| 2718 return bad_char_occurrence[char_code % kBMAlphabetSize]; | |
| 2719 } | |
| 2720 | |
| 2721 | |
| 2722 // Restricted simplified Boyer-Moore string matching. | |
| 2723 // Uses only the bad-shift table of Boyer-Moore and only uses it | |
| 2724 // for the character compared to the last character of the needle. | |
| 2725 template <typename schar, typename pchar> | |
| 2726 static int BoyerMooreHorspool(Vector<const schar> subject, | |
| 2727 Vector<const pchar> pattern, | |
| 2728 int start_index, | |
| 2729 bool* complete) { | |
| 2730 ASSERT(algorithm <= BOYER_MOORE_HORSPOOL); | |
| 2731 int n = subject.length(); | |
| 2732 int m = pattern.length(); | |
| 2733 | |
| 2734 int badness = -m; | |
| 2735 | |
| 2736 // How bad we are doing without a good-suffix table. | |
| 2737 int idx; // No matches found prior to this index. | |
| 2738 pchar last_char = pattern[m - 1]; | |
| 2739 int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char); | |
| 2740 // Perform search | |
| 2741 for (idx = start_index; idx <= n - m;) { | |
| 2742 int j = m - 1; | |
| 2743 int c; | |
| 2744 while (last_char != (c = subject[idx + j])) { | |
| 2745 int bc_occ = CharOccurrence<schar, pchar>(c); | |
| 2746 int shift = j - bc_occ; | |
| 2747 idx += shift; | |
| 2748 badness += 1 - shift; // at most zero, so badness cannot increase. | |
| 2749 if (idx > n - m) { | |
| 2750 *complete = true; | |
| 2751 return -1; | |
| 2752 } | |
| 2753 } | |
| 2754 j--; | |
| 2755 while (j >= 0 && pattern[j] == (subject[idx + j])) j--; | |
| 2756 if (j < 0) { | |
| 2757 *complete = true; | |
| 2758 return idx; | |
| 2759 } else { | |
| 2760 idx += last_char_shift; | |
| 2761 // Badness increases by the number of characters we have | |
| 2762 // checked, and decreases by the number of characters we | |
| 2763 // can skip by shifting. It's a measure of how we are doing | |
| 2764 // compared to reading each character exactly once. | |
| 2765 badness += (m - j) - last_char_shift; | |
| 2766 if (badness > 0) { | |
| 2767 *complete = false; | |
| 2768 return idx; | |
| 2769 } | |
| 2770 } | |
| 2771 } | |
| 2772 *complete = true; | |
| 2773 return -1; | |
| 2774 } | |
| 2775 | |
| 2776 | |
| 2777 template <typename schar, typename pchar> | |
| 2778 static int BoyerMooreIndexOf(Vector<const schar> subject, | |
| 2779 Vector<const pchar> pattern, | |
| 2780 int idx) { | |
| 2781 ASSERT(algorithm <= BOYER_MOORE); | |
| 2782 int n = subject.length(); | |
| 2783 int m = pattern.length(); | |
| 2784 // Only preprocess at most kBMMaxShift last characters of pattern. | |
| 2785 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift; | |
| 2786 | |
| 2787 pchar last_char = pattern[m - 1]; | |
| 2788 // Continue search from i. | |
| 2789 while (idx <= n - m) { | |
| 2790 int j = m - 1; | |
| 2791 schar c; | |
| 2792 while (last_char != (c = subject[idx + j])) { | |
| 2793 int shift = j - CharOccurrence<schar, pchar>(c); | |
| 2794 idx += shift; | |
| 2795 if (idx > n - m) { | |
| 2796 return -1; | |
| 2797 } | |
| 2798 } | |
| 2799 while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--; | |
| 2800 if (j < 0) { | |
| 2801 return idx; | |
| 2802 } else if (j < start) { | |
| 2803 // we have matched more than our tables allow us to be smart about. | |
| 2804 // Fall back on BMH shift. | |
| 2805 idx += m - 1 - CharOccurrence<schar, pchar>(last_char); | |
| 2806 } else { | |
| 2807 int gs_shift = bmgs_buffers.shift(j + 1); // Good suffix shift. | |
| 2808 int bc_occ = CharOccurrence<schar, pchar>(c); | |
| 2809 int shift = j - bc_occ; // Bad-char shift. | |
| 2810 if (gs_shift > shift) { | |
| 2811 shift = gs_shift; | |
| 2812 } | |
| 2813 idx += shift; | |
| 2814 } | |
| 2815 } | |
| 2816 | |
| 2817 return -1; | |
| 2818 } | |
| 2819 | |
| 2820 | |
| 2821 // Trivial string search for shorter strings. | |
| 2822 // On return, if "complete" is set to true, the return value is the | |
| 2823 // final result of searching for the patter in the subject. | |
| 2824 // If "complete" is set to false, the return value is the index where | |
| 2825 // further checking should start, i.e., it's guaranteed that the pattern | |
| 2826 // does not occur at a position prior to the returned index. | |
| 2827 template <typename pchar, typename schar> | |
| 2828 static int SimpleIndexOf(Vector<const schar> subject, | |
| 2829 Vector<const pchar> pattern, | |
| 2830 int idx, | |
| 2831 bool* complete) { | |
| 2832 ASSERT(pattern.length() > 1); | |
| 2833 int pattern_length = pattern.length(); | |
| 2834 // Badness is a count of how much work we have done. When we have | |
| 2835 // done enough work we decide it's probably worth switching to a better | |
| 2836 // algorithm. | |
| 2837 int badness = -10 - (pattern_length << 2); | |
| 2838 | |
| 2839 // We know our pattern is at least 2 characters, we cache the first so | |
| 2840 // the common case of the first character not matching is faster. | |
| 2841 pchar pattern_first_char = pattern[0]; | |
| 2842 for (int i = idx, n = subject.length() - pattern_length; i <= n; i++) { | |
| 2843 badness++; | |
| 2844 if (badness > 0) { | |
| 2845 *complete = false; | |
| 2846 return i; | |
| 2847 } | |
| 2848 if (sizeof(schar) == 1 && sizeof(pchar) == 1) { | |
| 2849 const schar* pos = reinterpret_cast<const schar*>( | |
| 2850 memchr(subject.start() + i, | |
| 2851 pattern_first_char, | |
| 2852 n - i + 1)); | |
| 2853 if (pos == NULL) { | |
| 2854 *complete = true; | |
| 2855 return -1; | |
| 2856 } | |
| 2857 i = static_cast<int>(pos - subject.start()); | |
| 2858 } else { | |
| 2859 if (subject[i] != pattern_first_char) continue; | |
| 2860 } | |
| 2861 int j = 1; | |
| 2862 do { | |
| 2863 if (pattern[j] != subject[i+j]) { | |
| 2864 break; | |
| 2865 } | |
| 2866 j++; | |
| 2867 } while (j < pattern_length); | |
| 2868 if (j == pattern_length) { | |
| 2869 *complete = true; | |
| 2870 return i; | |
| 2871 } | |
| 2872 badness += j; | |
| 2873 } | |
| 2874 *complete = true; | |
| 2875 return -1; | |
| 2876 } | |
| 2877 | |
| 2878 // Simple indexOf that never bails out. For short patterns only. | |
| 2879 template <typename pchar, typename schar> | |
| 2880 static int SimpleIndexOf(Vector<const schar> subject, | |
| 2881 Vector<const pchar> pattern, | |
| 2882 int idx) { | |
| 2883 int pattern_length = pattern.length(); | |
| 2884 pchar pattern_first_char = pattern[0]; | |
| 2885 for (int i = idx, n = subject.length() - pattern_length; i <= n; i++) { | |
| 2886 if (sizeof(schar) == 1 && sizeof(pchar) == 1) { | |
| 2887 const schar* pos = reinterpret_cast<const schar*>( | |
| 2888 memchr(subject.start() + i, | |
| 2889 pattern_first_char, | |
| 2890 n - i + 1)); | |
| 2891 if (pos == NULL) return -1; | |
| 2892 i = static_cast<int>(pos - subject.start()); | |
| 2893 } else { | |
| 2894 if (subject[i] != pattern_first_char) continue; | |
| 2895 } | |
| 2896 int j = 1; | |
| 2897 while (j < pattern_length) { | |
| 2898 if (pattern[j] != subject[i+j]) { | |
| 2899 break; | |
| 2900 } | |
| 2901 j++; | |
| 2902 } | |
| 2903 if (j == pattern_length) { | |
| 2904 return i; | |
| 2905 } | |
| 2906 } | |
| 2907 return -1; | |
| 2908 } | |
| 2909 | |
| 2910 | |
| 2911 // Strategy for searching for a string in another string. | |
| 2912 enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG }; | |
| 2913 | |
| 2914 | |
| 2915 template <typename pchar> | |
| 2916 static inline StringSearchStrategy InitializeStringSearch( | |
| 2917 Vector<const pchar> pat, bool ascii_subject) { | |
| 2918 // We have an ASCII haystack and a non-ASCII needle. Check if there | |
| 2919 // really is a non-ASCII character in the needle and bail out if there | |
| 2920 // is. | |
| 2921 if (ascii_subject && sizeof(pchar) > 1) { | |
| 2922 for (int i = 0; i < pat.length(); i++) { | |
| 2923 uc16 c = pat[i]; | |
| 2924 if (c > String::kMaxAsciiCharCode) { | |
| 2925 return SEARCH_FAIL; | |
| 2926 } | |
| 2927 } | |
| 2928 } | |
| 2929 if (pat.length() < kBMMinPatternLength) { | |
| 2930 return SEARCH_SHORT; | |
| 2931 } | |
| 2932 algorithm = SIMPLE_SEARCH; | |
| 2933 return SEARCH_LONG; | |
| 2934 } | |
| 2935 | |
| 2936 | |
| 2937 // Dispatch long needle searches to different algorithms. | |
| 2938 template <typename schar, typename pchar> | |
| 2939 static int ComplexIndexOf(Vector<const schar> sub, | |
| 2940 Vector<const pchar> pat, | |
| 2941 int start_index) { | |
| 2942 ASSERT(pat.length() >= kBMMinPatternLength); | |
| 2943 // Try algorithms in order of increasing setup cost and expected performance. | |
| 2944 bool complete; | |
| 2945 int idx = start_index; | |
| 2946 switch (algorithm) { | |
| 2947 case SIMPLE_SEARCH: | |
| 2948 idx = SimpleIndexOf(sub, pat, idx, &complete); | |
| 2949 if (complete) return idx; | |
| 2950 BoyerMoorePopulateBadCharTable(pat); | |
| 2951 algorithm = BOYER_MOORE_HORSPOOL; | |
| 2952 // FALLTHROUGH. | |
| 2953 case BOYER_MOORE_HORSPOOL: | |
| 2954 idx = BoyerMooreHorspool(sub, pat, idx, &complete); | |
| 2955 if (complete) return idx; | |
| 2956 // Build the Good Suffix table and continue searching. | |
| 2957 BoyerMoorePopulateGoodSuffixTable(pat); | |
| 2958 algorithm = BOYER_MOORE; | |
| 2959 // FALLTHROUGH. | |
| 2960 case BOYER_MOORE: | |
| 2961 return BoyerMooreIndexOf(sub, pat, idx); | |
| 2962 } | |
| 2963 UNREACHABLE(); | |
| 2964 return -1; | |
| 2965 } | |
| 2966 | |
| 2967 | |
| 2968 // Dispatch to different search strategies for a single search. | |
| 2969 // If searching multiple times on the same needle, the search | |
| 2970 // strategy should only be computed once and then dispatch to different | |
| 2971 // loops. | |
| 2972 template <typename schar, typename pchar> | |
| 2973 static int StringSearch(Vector<const schar> sub, | |
| 2974 Vector<const pchar> pat, | |
| 2975 int start_index) { | |
| 2976 bool ascii_subject = (sizeof(schar) == 1); | |
| 2977 StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject); | |
| 2978 switch (strategy) { | |
| 2979 case SEARCH_FAIL: return -1; | |
| 2980 case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index); | |
| 2981 case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index); | |
| 2982 } | |
| 2983 UNREACHABLE(); | |
| 2984 return -1; | |
| 2985 } | |
| 2986 | |
| 2987 | |
| 2988 // Perform string match of pattern on subject, starting at start index. | 2575 // Perform string match of pattern on subject, starting at start index. |
| 2989 // Caller must ensure that 0 <= start_index <= sub->length(), | 2576 // Caller must ensure that 0 <= start_index <= sub->length(), |
| 2990 // and should check that pat->length() + start_index <= sub->length() | 2577 // and should check that pat->length() + start_index <= sub->length() |
| 2991 int Runtime::StringMatch(Handle<String> sub, | 2578 int Runtime::StringMatch(Handle<String> sub, |
| 2992 Handle<String> pat, | 2579 Handle<String> pat, |
| 2993 int start_index) { | 2580 int start_index) { |
| 2994 ASSERT(0 <= start_index); | 2581 ASSERT(0 <= start_index); |
| 2995 ASSERT(start_index <= sub->length()); | 2582 ASSERT(start_index <= sub->length()); |
| 2996 | 2583 |
| 2997 int pattern_length = pat->length(); | 2584 int pattern_length = pat->length(); |
| (...skipping 2165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5163 int right = length; | 4750 int right = length; |
| 5164 if (trimRight) { | 4751 if (trimRight) { |
| 5165 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { | 4752 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { |
| 5166 right--; | 4753 right--; |
| 5167 } | 4754 } |
| 5168 } | 4755 } |
| 5169 return s->SubString(left, right); | 4756 return s->SubString(left, right); |
| 5170 } | 4757 } |
| 5171 | 4758 |
| 5172 | 4759 |
| 4760 // Define storage for buffers declared in header file. |
| 4761 // TODO(lrn): Remove these when rewriting search code. |
| 4762 int BMBuffers::bad_char_occurrence[kBMAlphabetSize]; |
| 4763 BMGoodSuffixBuffers BMBuffers::bmgs_buffers; |
| 4764 |
| 4765 |
| 5173 template <typename schar, typename pchar> | 4766 template <typename schar, typename pchar> |
| 5174 void FindStringIndices(Vector<const schar> subject, | 4767 void FindStringIndices(Vector<const schar> subject, |
| 5175 Vector<const pchar> pattern, | 4768 Vector<const pchar> pattern, |
| 5176 ZoneList<int>* indices, | 4769 ZoneList<int>* indices, |
| 5177 unsigned int limit) { | 4770 unsigned int limit) { |
| 5178 ASSERT(limit > 0); | 4771 ASSERT(limit > 0); |
| 5179 // Collect indices of pattern in subject, and the end-of-string index. | 4772 // Collect indices of pattern in subject, and the end-of-string index. |
| 5180 // Stop after finding at most limit values. | 4773 // Stop after finding at most limit values. |
| 5181 StringSearchStrategy strategy = | 4774 StringSearchStrategy strategy = |
| 5182 InitializeStringSearch(pattern, sizeof(schar) == 1); | 4775 InitializeStringSearch(pattern, sizeof(schar) == 1); |
| (...skipping 5350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10533 } else { | 10126 } else { |
| 10534 // Handle last resort GC and make sure to allow future allocations | 10127 // Handle last resort GC and make sure to allow future allocations |
| 10535 // to grow the heap without causing GCs (if possible). | 10128 // to grow the heap without causing GCs (if possible). |
| 10536 Counters::gc_last_resort_from_js.Increment(); | 10129 Counters::gc_last_resort_from_js.Increment(); |
| 10537 Heap::CollectAllGarbage(false); | 10130 Heap::CollectAllGarbage(false); |
| 10538 } | 10131 } |
| 10539 } | 10132 } |
| 10540 | 10133 |
| 10541 | 10134 |
| 10542 } } // namespace v8::internal | 10135 } } // namespace v8::internal |
| OLD | NEW |