| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2881 limit, | 2881 limit, |
| 2882 zone); | 2882 zone); |
| 2883 } | 2883 } |
| 2884 } | 2884 } |
| 2885 } | 2885 } |
| 2886 } | 2886 } |
| 2887 } | 2887 } |
| 2888 | 2888 |
| 2889 | 2889 |
| 2890 template<typename ResultSeqString> | 2890 template<typename ResultSeqString> |
| 2891 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString( | 2891 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString( |
| 2892 Isolate* isolate, | 2892 Isolate* isolate, |
| 2893 Handle<String> subject, | 2893 Handle<String> subject, |
| 2894 Handle<JSRegExp> pattern_regexp, | 2894 Handle<JSRegExp> pattern_regexp, |
| 2895 Handle<String> replacement, | 2895 Handle<String> replacement, |
| 2896 Handle<JSArray> last_match_info) { | 2896 Handle<JSArray> last_match_info) { |
| 2897 ASSERT(subject->IsFlat()); | 2897 ASSERT(subject->IsFlat()); |
| 2898 ASSERT(replacement->IsFlat()); | 2898 ASSERT(replacement->IsFlat()); |
| 2899 | 2899 |
| 2900 Zone* zone = isolate->runtime_zone(); | 2900 Zone* zone = isolate->runtime_zone(); |
| 2901 ZoneScope zone_space(zone, DELETE_ON_EXIT); | 2901 ZoneScope zone_space(zone, DELETE_ON_EXIT); |
| 2902 ZoneList<int> indices(8, zone); | 2902 ZoneList<int> indices(8, zone); |
| 2903 ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); | 2903 ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); |
| 2904 String* pattern = | 2904 String* pattern = |
| 2905 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); | 2905 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); |
| 2906 int subject_len = subject->length(); | 2906 int subject_len = subject->length(); |
| 2907 int pattern_len = pattern->length(); | 2907 int pattern_len = pattern->length(); |
| 2908 int replacement_len = replacement->length(); | 2908 int replacement_len = replacement->length(); |
| 2909 | 2909 |
| 2910 FindStringIndicesDispatch( | 2910 FindStringIndicesDispatch( |
| 2911 isolate, *subject, pattern, &indices, 0xffffffff, zone); | 2911 isolate, *subject, pattern, &indices, 0xffffffff, zone); |
| 2912 | 2912 |
| 2913 int matches = indices.length(); | 2913 int matches = indices.length(); |
| 2914 if (matches == 0) { | 2914 if (matches == 0) return *subject; |
| 2915 return isolate->heap()->undefined_value(); | |
| 2916 } | |
| 2917 | 2915 |
| 2918 // Detect integer overflow. | 2916 // Detect integer overflow. |
| 2919 int64_t result_len_64 = | 2917 int64_t result_len_64 = |
| 2920 (static_cast<int64_t>(replacement_len) - | 2918 (static_cast<int64_t>(replacement_len) - |
| 2921 static_cast<int64_t>(pattern_len)) * | 2919 static_cast<int64_t>(pattern_len)) * |
| 2922 static_cast<int64_t>(matches) + | 2920 static_cast<int64_t>(matches) + |
| 2923 static_cast<int64_t>(subject_len); | 2921 static_cast<int64_t>(subject_len); |
| 2924 if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11); | 2922 if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11); |
| 2925 int result_len = static_cast<int>(result_len_64); | 2923 int result_len = static_cast<int>(result_len_64); |
| 2926 | 2924 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2966 } | 2964 } |
| 2967 | 2965 |
| 2968 int32_t match_indices[] = { indices.at(matches - 1), | 2966 int32_t match_indices[] = { indices.at(matches - 1), |
| 2969 indices.at(matches - 1) + pattern_len }; | 2967 indices.at(matches - 1) + pattern_len }; |
| 2970 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); | 2968 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); |
| 2971 | 2969 |
| 2972 return *result; | 2970 return *result; |
| 2973 } | 2971 } |
| 2974 | 2972 |
| 2975 | 2973 |
| 2976 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( | 2974 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString( |
| 2977 Isolate* isolate, | 2975 Isolate* isolate, |
| 2978 Handle<String> subject, | 2976 Handle<String> subject, |
| 2979 Handle<JSRegExp> regexp, | 2977 Handle<JSRegExp> regexp, |
| 2980 Handle<String> replacement, | 2978 Handle<String> replacement, |
| 2981 Handle<JSArray> last_match_info) { | 2979 Handle<JSArray> last_match_info) { |
| 2982 ASSERT(subject->IsFlat()); | 2980 ASSERT(subject->IsFlat()); |
| 2983 ASSERT(replacement->IsFlat()); | 2981 ASSERT(replacement->IsFlat()); |
| 2984 | 2982 |
| 2985 bool is_global = regexp->GetFlags().is_global(); | |
| 2986 int capture_count = regexp->CaptureCount(); | 2983 int capture_count = regexp->CaptureCount(); |
| 2987 int subject_length = subject->length(); | 2984 int subject_length = subject->length(); |
| 2988 | 2985 |
| 2989 // CompiledReplacement uses zone allocation. | 2986 // CompiledReplacement uses zone allocation. |
| 2990 Zone* zone = isolate->runtime_zone(); | 2987 Zone* zone = isolate->runtime_zone(); |
| 2991 ZoneScope zonescope(zone, DELETE_ON_EXIT); | 2988 ZoneScope zonescope(zone, DELETE_ON_EXIT); |
| 2992 CompiledReplacement compiled_replacement(zone); | 2989 CompiledReplacement compiled_replacement(zone); |
| 2993 bool simple_replace = compiled_replacement.Compile(replacement, | 2990 bool simple_replace = compiled_replacement.Compile(replacement, |
| 2994 capture_count, | 2991 capture_count, |
| 2995 subject_length); | 2992 subject_length); |
| 2996 | 2993 |
| 2997 // Shortcut for simple non-regexp global replacements | 2994 // Shortcut for simple non-regexp global replacements |
| 2998 if (is_global && | 2995 if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) { |
| 2999 regexp->TypeTag() == JSRegExp::ATOM && | |
| 3000 simple_replace) { | |
| 3001 if (subject->IsOneByteConvertible() && | 2996 if (subject->IsOneByteConvertible() && |
| 3002 replacement->IsOneByteConvertible()) { | 2997 replacement->IsOneByteConvertible()) { |
| 3003 return StringReplaceAtomRegExpWithString<SeqOneByteString>( | 2998 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>( |
| 3004 isolate, subject, regexp, replacement, last_match_info); | 2999 isolate, subject, regexp, replacement, last_match_info); |
| 3005 } else { | 3000 } else { |
| 3006 return StringReplaceAtomRegExpWithString<SeqTwoByteString>( | 3001 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>( |
| 3007 isolate, subject, regexp, replacement, last_match_info); | 3002 isolate, subject, regexp, replacement, last_match_info); |
| 3008 } | 3003 } |
| 3009 } | 3004 } |
| 3010 | 3005 |
| 3011 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate); | 3006 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); |
| 3012 if (global_cache.HasException()) return Failure::Exception(); | 3007 if (global_cache.HasException()) return Failure::Exception(); |
| 3013 | 3008 |
| 3014 int32_t* current_match = global_cache.FetchNext(); | 3009 int32_t* current_match = global_cache.FetchNext(); |
| 3015 if (current_match == NULL) { | 3010 if (current_match == NULL) { |
| 3016 if (global_cache.HasException()) return Failure::Exception(); | 3011 if (global_cache.HasException()) return Failure::Exception(); |
| 3017 return isolate->heap()->undefined_value(); | 3012 return *subject; |
| 3018 } | 3013 } |
| 3019 | 3014 |
| 3020 // Guessing the number of parts that the final result string is built | 3015 // Guessing the number of parts that the final result string is built |
| 3021 // from. Global regexps can match any number of times, so we guess | 3016 // from. Global regexps can match any number of times, so we guess |
| 3022 // conservatively. | 3017 // conservatively. |
| 3023 int expected_parts = | 3018 int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1; |
| 3024 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1; | |
| 3025 ReplacementStringBuilder builder(isolate->heap(), | 3019 ReplacementStringBuilder builder(isolate->heap(), |
| 3026 subject, | 3020 subject, |
| 3027 expected_parts); | 3021 expected_parts); |
| 3028 | 3022 |
| 3029 // Number of parts added by compiled replacement plus preceeding | 3023 // Number of parts added by compiled replacement plus preceeding |
| 3030 // string and possibly suffix after last match. It is possible for | 3024 // string and possibly suffix after last match. It is possible for |
| 3031 // all components to use two elements when encoded as two smis. | 3025 // all components to use two elements when encoded as two smis. |
| 3032 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2); | 3026 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2); |
| 3033 | 3027 |
| 3034 int prev = 0; | 3028 int prev = 0; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3046 if (simple_replace) { | 3040 if (simple_replace) { |
| 3047 builder.AddString(replacement); | 3041 builder.AddString(replacement); |
| 3048 } else { | 3042 } else { |
| 3049 compiled_replacement.Apply(&builder, | 3043 compiled_replacement.Apply(&builder, |
| 3050 start, | 3044 start, |
| 3051 end, | 3045 end, |
| 3052 current_match); | 3046 current_match); |
| 3053 } | 3047 } |
| 3054 prev = end; | 3048 prev = end; |
| 3055 | 3049 |
| 3056 // Only continue checking for global regexps. | |
| 3057 if (!is_global) break; | |
| 3058 | |
| 3059 current_match = global_cache.FetchNext(); | 3050 current_match = global_cache.FetchNext(); |
| 3060 } while (current_match != NULL); | 3051 } while (current_match != NULL); |
| 3061 | 3052 |
| 3062 if (global_cache.HasException()) return Failure::Exception(); | 3053 if (global_cache.HasException()) return Failure::Exception(); |
| 3063 | 3054 |
| 3064 if (prev < subject_length) { | 3055 if (prev < subject_length) { |
| 3065 builder.EnsureCapacity(2); | 3056 builder.EnsureCapacity(2); |
| 3066 builder.AddSubjectSlice(prev, subject_length); | 3057 builder.AddSubjectSlice(prev, subject_length); |
| 3067 } | 3058 } |
| 3068 | 3059 |
| 3069 RegExpImpl::SetLastMatchInfo(last_match_info, | 3060 RegExpImpl::SetLastMatchInfo(last_match_info, |
| 3070 subject, | 3061 subject, |
| 3071 capture_count, | 3062 capture_count, |
| 3072 global_cache.LastSuccessfulMatch()); | 3063 global_cache.LastSuccessfulMatch()); |
| 3073 | 3064 |
| 3074 return *(builder.ToString()); | 3065 return *(builder.ToString()); |
| 3075 } | 3066 } |
| 3076 | 3067 |
| 3077 | 3068 |
| 3078 template <typename ResultSeqString> | 3069 template <typename ResultSeqString> |
| 3079 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( | 3070 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString( |
| 3080 Isolate* isolate, | 3071 Isolate* isolate, |
| 3081 Handle<String> subject, | 3072 Handle<String> subject, |
| 3082 Handle<JSRegExp> regexp, | 3073 Handle<JSRegExp> regexp, |
| 3083 Handle<JSArray> last_match_info) { | 3074 Handle<JSArray> last_match_info) { |
| 3084 ASSERT(subject->IsFlat()); | 3075 ASSERT(subject->IsFlat()); |
| 3085 | 3076 |
| 3086 bool is_global = regexp->GetFlags().is_global(); | |
| 3087 | |
| 3088 // Shortcut for simple non-regexp global replacements | 3077 // Shortcut for simple non-regexp global replacements |
| 3089 if (is_global && | 3078 if (regexp->TypeTag() == JSRegExp::ATOM) { |
| 3090 regexp->TypeTag() == JSRegExp::ATOM) { | |
| 3091 Handle<String> empty_string = isolate->factory()->empty_string(); | 3079 Handle<String> empty_string = isolate->factory()->empty_string(); |
| 3092 if (subject->IsOneByteRepresentation()) { | 3080 if (subject->IsOneByteRepresentation()) { |
| 3093 return StringReplaceAtomRegExpWithString<SeqOneByteString>( | 3081 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>( |
| 3094 isolate, | 3082 isolate, subject, regexp, empty_string, last_match_info); |
| 3095 subject, | |
| 3096 regexp, | |
| 3097 empty_string, | |
| 3098 last_match_info); | |
| 3099 } else { | 3083 } else { |
| 3100 return StringReplaceAtomRegExpWithString<SeqTwoByteString>( | 3084 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>( |
| 3101 isolate, | 3085 isolate, subject, regexp, empty_string, last_match_info); |
| 3102 subject, | |
| 3103 regexp, | |
| 3104 empty_string, | |
| 3105 last_match_info); | |
| 3106 } | 3086 } |
| 3107 } | 3087 } |
| 3108 | 3088 |
| 3109 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate); | 3089 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); |
| 3110 if (global_cache.HasException()) return Failure::Exception(); | 3090 if (global_cache.HasException()) return Failure::Exception(); |
| 3111 | 3091 |
| 3112 int32_t* current_match = global_cache.FetchNext(); | 3092 int32_t* current_match = global_cache.FetchNext(); |
| 3113 if (current_match == NULL) { | 3093 if (current_match == NULL) { |
| 3114 if (global_cache.HasException()) return Failure::Exception(); | 3094 if (global_cache.HasException()) return Failure::Exception(); |
| 3115 return isolate->heap()->undefined_value(); | 3095 return *subject; |
| 3116 } | 3096 } |
| 3117 | 3097 |
| 3118 int start = current_match[0]; | 3098 int start = current_match[0]; |
| 3119 int end = current_match[1]; | 3099 int end = current_match[1]; |
| 3120 int capture_count = regexp->CaptureCount(); | 3100 int capture_count = regexp->CaptureCount(); |
| 3121 int subject_length = subject->length(); | 3101 int subject_length = subject->length(); |
| 3122 | 3102 |
| 3123 int new_length = subject_length - (end - start); | 3103 int new_length = subject_length - (end - start); |
| 3124 if (new_length == 0) return isolate->heap()->empty_string(); | 3104 if (new_length == 0) return isolate->heap()->empty_string(); |
| 3125 | 3105 |
| 3126 Handle<ResultSeqString> answer; | 3106 Handle<ResultSeqString> answer; |
| 3127 if (ResultSeqString::kHasAsciiEncoding) { | 3107 if (ResultSeqString::kHasAsciiEncoding) { |
| 3128 answer = Handle<ResultSeqString>::cast( | 3108 answer = Handle<ResultSeqString>::cast( |
| 3129 isolate->factory()->NewRawOneByteString(new_length)); | 3109 isolate->factory()->NewRawOneByteString(new_length)); |
| 3130 } else { | 3110 } else { |
| 3131 answer = Handle<ResultSeqString>::cast( | 3111 answer = Handle<ResultSeqString>::cast( |
| 3132 isolate->factory()->NewRawTwoByteString(new_length)); | 3112 isolate->factory()->NewRawTwoByteString(new_length)); |
| 3133 } | 3113 } |
| 3134 | 3114 |
| 3135 if (!is_global) { | |
| 3136 RegExpImpl::SetLastMatchInfo( | |
| 3137 last_match_info, subject, capture_count, current_match); | |
| 3138 if (start == end) { | |
| 3139 return *subject; | |
| 3140 } else { | |
| 3141 if (start > 0) { | |
| 3142 String::WriteToFlat(*subject, answer->GetChars(), 0, start); | |
| 3143 } | |
| 3144 if (end < subject_length) { | |
| 3145 String::WriteToFlat( | |
| 3146 *subject, answer->GetChars() + start, end, subject_length); | |
| 3147 } | |
| 3148 return *answer; | |
| 3149 } | |
| 3150 } | |
| 3151 | |
| 3152 int prev = 0; | 3115 int prev = 0; |
| 3153 int position = 0; | 3116 int position = 0; |
| 3154 | 3117 |
| 3155 do { | 3118 do { |
| 3156 start = current_match[0]; | 3119 start = current_match[0]; |
| 3157 end = current_match[1]; | 3120 end = current_match[1]; |
| 3158 if (prev < start) { | 3121 if (prev < start) { |
| 3159 // Add substring subject[prev;start] to answer string. | 3122 // Add substring subject[prev;start] to answer string. |
| 3160 String::WriteToFlat( | 3123 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); |
| 3161 *subject, answer->GetChars() + position, prev, start); | |
| 3162 position += start - prev; | 3124 position += start - prev; |
| 3163 } | 3125 } |
| 3164 prev = end; | 3126 prev = end; |
| 3165 | 3127 |
| 3166 current_match = global_cache.FetchNext(); | 3128 current_match = global_cache.FetchNext(); |
| 3167 } while (current_match != NULL); | 3129 } while (current_match != NULL); |
| 3168 | 3130 |
| 3169 if (global_cache.HasException()) return Failure::Exception(); | 3131 if (global_cache.HasException()) return Failure::Exception(); |
| 3170 | 3132 |
| 3171 RegExpImpl::SetLastMatchInfo(last_match_info, | 3133 RegExpImpl::SetLastMatchInfo(last_match_info, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3193 Address end_of_string = answer->address() + string_size; | 3155 Address end_of_string = answer->address() + string_size; |
| 3194 isolate->heap()->CreateFillerObjectAt(end_of_string, delta); | 3156 isolate->heap()->CreateFillerObjectAt(end_of_string, delta); |
| 3195 if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) { | 3157 if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) { |
| 3196 MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta); | 3158 MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta); |
| 3197 } | 3159 } |
| 3198 | 3160 |
| 3199 return *answer; | 3161 return *answer; |
| 3200 } | 3162 } |
| 3201 | 3163 |
| 3202 | 3164 |
| 3203 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) { | 3165 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) { |
| 3204 ASSERT(args.length() == 4); | 3166 ASSERT(args.length() == 4); |
| 3205 | 3167 |
| 3206 HandleScope scope(isolate); | 3168 HandleScope scope(isolate); |
| 3207 | 3169 |
| 3208 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 3170 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 3209 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); | 3171 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); |
| 3210 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); | 3172 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); |
| 3211 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); | 3173 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); |
| 3212 | 3174 |
| 3175 ASSERT(regexp->GetFlags().is_global()); |
| 3176 |
| 3213 if (!subject->IsFlat()) subject = FlattenGetString(subject); | 3177 if (!subject->IsFlat()) subject = FlattenGetString(subject); |
| 3214 | 3178 |
| 3215 if (!replacement->IsFlat()) replacement = FlattenGetString(replacement); | 3179 if (!replacement->IsFlat()) replacement = FlattenGetString(replacement); |
| 3216 | 3180 |
| 3217 ASSERT(last_match_info->HasFastObjectElements()); | 3181 ASSERT(last_match_info->HasFastObjectElements()); |
| 3218 | 3182 |
| 3219 if (replacement->length() == 0) { | 3183 if (replacement->length() == 0) { |
| 3220 if (subject->IsOneByteConvertible()) { | 3184 if (subject->IsOneByteConvertible()) { |
| 3221 return StringReplaceRegExpWithEmptyString<SeqOneByteString>( | 3185 return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>( |
| 3222 isolate, subject, regexp, last_match_info); | 3186 isolate, subject, regexp, last_match_info); |
| 3223 } else { | 3187 } else { |
| 3224 return StringReplaceRegExpWithEmptyString<SeqTwoByteString>( | 3188 return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>( |
| 3225 isolate, subject, regexp, last_match_info); | 3189 isolate, subject, regexp, last_match_info); |
| 3226 } | 3190 } |
| 3227 } | 3191 } |
| 3228 | 3192 |
| 3229 return StringReplaceRegExpWithString( | 3193 return StringReplaceGlobalRegExpWithString( |
| 3230 isolate, subject, regexp, replacement, last_match_info); | 3194 isolate, subject, regexp, replacement, last_match_info); |
| 3231 } | 3195 } |
| 3232 | 3196 |
| 3233 | 3197 |
| 3234 Handle<String> StringReplaceOneCharWithString(Isolate* isolate, | 3198 Handle<String> StringReplaceOneCharWithString(Isolate* isolate, |
| 3235 Handle<String> subject, | 3199 Handle<String> subject, |
| 3236 Handle<String> search, | 3200 Handle<String> search, |
| 3237 Handle<String> replace, | 3201 Handle<String> replace, |
| 3238 bool* found, | 3202 bool* found, |
| 3239 int recursion_limit) { | 3203 int recursion_limit) { |
| (...skipping 10287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13527 // Handle last resort GC and make sure to allow future allocations | 13491 // Handle last resort GC and make sure to allow future allocations |
| 13528 // to grow the heap without causing GCs (if possible). | 13492 // to grow the heap without causing GCs (if possible). |
| 13529 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13493 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13530 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13494 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 13531 "Runtime::PerformGC"); | 13495 "Runtime::PerformGC"); |
| 13532 } | 13496 } |
| 13533 } | 13497 } |
| 13534 | 13498 |
| 13535 | 13499 |
| 13536 } } // namespace v8::internal | 13500 } } // namespace v8::internal |
| OLD | NEW |