| 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 3312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3323 | 3323 |
| 3324 class ReplacementStringBuilder { | 3324 class ReplacementStringBuilder { |
| 3325 public: | 3325 public: |
| 3326 ReplacementStringBuilder(Heap* heap, | 3326 ReplacementStringBuilder(Heap* heap, |
| 3327 Handle<String> subject, | 3327 Handle<String> subject, |
| 3328 int estimated_part_count) | 3328 int estimated_part_count) |
| 3329 : heap_(heap), | 3329 : heap_(heap), |
| 3330 array_builder_(heap->isolate(), estimated_part_count), | 3330 array_builder_(heap->isolate(), estimated_part_count), |
| 3331 subject_(subject), | 3331 subject_(subject), |
| 3332 character_count_(0), | 3332 character_count_(0), |
| 3333 is_ascii_(subject->IsOneByteRepresentation()) { | 3333 is_ascii_(subject->IsOneByteRepresentation()), |
| 3334 overflowed_(false) { |
| 3334 // Require a non-zero initial size. Ensures that doubling the size to | 3335 // Require a non-zero initial size. Ensures that doubling the size to |
| 3335 // extend the array will work. | 3336 // extend the array will work. |
| 3336 ASSERT(estimated_part_count > 0); | 3337 ASSERT(estimated_part_count > 0); |
| 3337 } | 3338 } |
| 3338 | 3339 |
| 3339 static inline void AddSubjectSlice(FixedArrayBuilder* builder, | 3340 static inline void AddSubjectSlice(FixedArrayBuilder* builder, |
| 3340 int from, | 3341 int from, |
| 3341 int to) { | 3342 int to) { |
| 3342 ASSERT(from >= 0); | 3343 ASSERT(from >= 0); |
| 3343 int length = to - from; | 3344 int length = to - from; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3371 ASSERT(length > 0); | 3372 ASSERT(length > 0); |
| 3372 AddElement(*string); | 3373 AddElement(*string); |
| 3373 if (!string->IsOneByteRepresentation()) { | 3374 if (!string->IsOneByteRepresentation()) { |
| 3374 is_ascii_ = false; | 3375 is_ascii_ = false; |
| 3375 } | 3376 } |
| 3376 IncrementCharacterCount(length); | 3377 IncrementCharacterCount(length); |
| 3377 } | 3378 } |
| 3378 | 3379 |
| 3379 | 3380 |
| 3380 Handle<String> ToString() { | 3381 Handle<String> ToString() { |
| 3382 if (overflowed_) { |
| 3383 heap_->isolate()->ThrowInvalidStringLength(); |
| 3384 return Handle<String>(); |
| 3385 } |
| 3386 |
| 3381 if (array_builder_.length() == 0) { | 3387 if (array_builder_.length() == 0) { |
| 3382 return heap_->isolate()->factory()->empty_string(); | 3388 return heap_->isolate()->factory()->empty_string(); |
| 3383 } | 3389 } |
| 3384 | 3390 |
| 3385 Handle<String> joined_string; | 3391 Handle<String> joined_string; |
| 3386 if (is_ascii_) { | 3392 if (is_ascii_) { |
| 3387 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); | 3393 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); |
| 3388 DisallowHeapAllocation no_gc; | 3394 DisallowHeapAllocation no_gc; |
| 3389 uint8_t* char_buffer = seq->GetChars(); | 3395 uint8_t* char_buffer = seq->GetChars(); |
| 3390 StringBuilderConcatHelper(*subject_, | 3396 StringBuilderConcatHelper(*subject_, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3402 *array_builder_.array(), | 3408 *array_builder_.array(), |
| 3403 array_builder_.length()); | 3409 array_builder_.length()); |
| 3404 joined_string = Handle<String>::cast(seq); | 3410 joined_string = Handle<String>::cast(seq); |
| 3405 } | 3411 } |
| 3406 return joined_string; | 3412 return joined_string; |
| 3407 } | 3413 } |
| 3408 | 3414 |
| 3409 | 3415 |
| 3410 void IncrementCharacterCount(int by) { | 3416 void IncrementCharacterCount(int by) { |
| 3411 if (character_count_ > String::kMaxLength - by) { | 3417 if (character_count_ > String::kMaxLength - by) { |
| 3412 V8::FatalProcessOutOfMemory("String.replace result too large."); | 3418 overflowed_ = true; |
| 3413 } | 3419 } |
| 3414 character_count_ += by; | 3420 character_count_ += by; |
| 3415 } | 3421 } |
| 3416 | 3422 |
| 3417 private: | 3423 private: |
| 3418 Handle<SeqOneByteString> NewRawOneByteString(int length) { | 3424 Handle<SeqOneByteString> NewRawOneByteString(int length) { |
| 3419 return heap_->isolate()->factory()->NewRawOneByteString(length); | 3425 return heap_->isolate()->factory()->NewRawOneByteString(length); |
| 3420 } | 3426 } |
| 3421 | 3427 |
| 3422 | 3428 |
| 3423 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { | 3429 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { |
| 3424 return heap_->isolate()->factory()->NewRawTwoByteString(length); | 3430 return heap_->isolate()->factory()->NewRawTwoByteString(length); |
| 3425 } | 3431 } |
| 3426 | 3432 |
| 3427 | 3433 |
| 3428 void AddElement(Object* element) { | 3434 void AddElement(Object* element) { |
| 3429 ASSERT(element->IsSmi() || element->IsString()); | 3435 ASSERT(element->IsSmi() || element->IsString()); |
| 3430 ASSERT(array_builder_.capacity() > array_builder_.length()); | 3436 ASSERT(array_builder_.capacity() > array_builder_.length()); |
| 3431 array_builder_.Add(element); | 3437 array_builder_.Add(element); |
| 3432 } | 3438 } |
| 3433 | 3439 |
| 3434 Heap* heap_; | 3440 Heap* heap_; |
| 3435 FixedArrayBuilder array_builder_; | 3441 FixedArrayBuilder array_builder_; |
| 3436 Handle<String> subject_; | 3442 Handle<String> subject_; |
| 3437 int character_count_; | 3443 int character_count_; |
| 3438 bool is_ascii_; | 3444 bool is_ascii_; |
| 3445 bool overflowed_; |
| 3439 }; | 3446 }; |
| 3440 | 3447 |
| 3441 | 3448 |
| 3442 class CompiledReplacement { | 3449 class CompiledReplacement { |
| 3443 public: | 3450 public: |
| 3444 explicit CompiledReplacement(Zone* zone) | 3451 explicit CompiledReplacement(Zone* zone) |
| 3445 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} | 3452 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} |
| 3446 | 3453 |
| 3447 // Return whether the replacement is simple. | 3454 // Return whether the replacement is simple. |
| 3448 bool Compile(Handle<String> replacement, | 3455 bool Compile(Handle<String> replacement, |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4027 if (prev < subject_length) { | 4034 if (prev < subject_length) { |
| 4028 builder.EnsureCapacity(2); | 4035 builder.EnsureCapacity(2); |
| 4029 builder.AddSubjectSlice(prev, subject_length); | 4036 builder.AddSubjectSlice(prev, subject_length); |
| 4030 } | 4037 } |
| 4031 | 4038 |
| 4032 RegExpImpl::SetLastMatchInfo(last_match_info, | 4039 RegExpImpl::SetLastMatchInfo(last_match_info, |
| 4033 subject, | 4040 subject, |
| 4034 capture_count, | 4041 capture_count, |
| 4035 global_cache.LastSuccessfulMatch()); | 4042 global_cache.LastSuccessfulMatch()); |
| 4036 | 4043 |
| 4037 return *(builder.ToString()); | 4044 Handle<String> result = builder.ToString(); |
| 4045 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 4046 return *result; |
| 4038 } | 4047 } |
| 4039 | 4048 |
| 4040 | 4049 |
| 4041 template <typename ResultSeqString> | 4050 template <typename ResultSeqString> |
| 4042 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString( | 4051 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString( |
| 4043 Isolate* isolate, | 4052 Isolate* isolate, |
| 4044 Handle<String> subject, | 4053 Handle<String> subject, |
| 4045 Handle<JSRegExp> regexp, | 4054 Handle<JSRegExp> regexp, |
| 4046 Handle<JSArray> last_match_info) { | 4055 Handle<JSArray> last_match_info) { |
| 4047 ASSERT(subject->IsFlat()); | 4056 ASSERT(subject->IsFlat()); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4173 ConsString* cons = ConsString::cast(*subject); | 4182 ConsString* cons = ConsString::cast(*subject); |
| 4174 Handle<String> first = Handle<String>(cons->first()); | 4183 Handle<String> first = Handle<String>(cons->first()); |
| 4175 Handle<String> second = Handle<String>(cons->second()); | 4184 Handle<String> second = Handle<String>(cons->second()); |
| 4176 Handle<String> new_first = | 4185 Handle<String> new_first = |
| 4177 StringReplaceOneCharWithString(isolate, | 4186 StringReplaceOneCharWithString(isolate, |
| 4178 first, | 4187 first, |
| 4179 search, | 4188 search, |
| 4180 replace, | 4189 replace, |
| 4181 found, | 4190 found, |
| 4182 recursion_limit - 1); | 4191 recursion_limit - 1); |
| 4192 if (new_first.is_null()) return new_first; |
| 4183 if (*found) return isolate->factory()->NewConsString(new_first, second); | 4193 if (*found) return isolate->factory()->NewConsString(new_first, second); |
| 4184 if (new_first.is_null()) return new_first; | |
| 4185 | 4194 |
| 4186 Handle<String> new_second = | 4195 Handle<String> new_second = |
| 4187 StringReplaceOneCharWithString(isolate, | 4196 StringReplaceOneCharWithString(isolate, |
| 4188 second, | 4197 second, |
| 4189 search, | 4198 search, |
| 4190 replace, | 4199 replace, |
| 4191 found, | 4200 found, |
| 4192 recursion_limit - 1); | 4201 recursion_limit - 1); |
| 4202 if (new_second.is_null()) return new_second; |
| 4193 if (*found) return isolate->factory()->NewConsString(first, new_second); | 4203 if (*found) return isolate->factory()->NewConsString(first, new_second); |
| 4194 if (new_second.is_null()) return new_second; | |
| 4195 | 4204 |
| 4196 return subject; | 4205 return subject; |
| 4197 } else { | 4206 } else { |
| 4198 int index = Runtime::StringMatch(isolate, subject, search, 0); | 4207 int index = Runtime::StringMatch(isolate, subject, search, 0); |
| 4199 if (index == -1) return subject; | 4208 if (index == -1) return subject; |
| 4200 *found = true; | 4209 *found = true; |
| 4201 Handle<String> first = isolate->factory()->NewSubString(subject, 0, index); | 4210 Handle<String> first = isolate->factory()->NewSubString(subject, 0, index); |
| 4202 Handle<String> cons1 = isolate->factory()->NewConsString(first, replace); | 4211 Handle<String> cons1 = isolate->factory()->NewConsString(first, replace); |
| 4212 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>()); |
| 4203 Handle<String> second = | 4213 Handle<String> second = |
| 4204 isolate->factory()->NewSubString(subject, index + 1, subject->length()); | 4214 isolate->factory()->NewSubString(subject, index + 1, subject->length()); |
| 4205 return isolate->factory()->NewConsString(cons1, second); | 4215 return isolate->factory()->NewConsString(cons1, second); |
| 4206 } | 4216 } |
| 4207 } | 4217 } |
| 4208 | 4218 |
| 4209 | 4219 |
| 4210 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) { | 4220 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) { |
| 4211 HandleScope scope(isolate); | 4221 HandleScope scope(isolate); |
| 4212 ASSERT(args.length() == 3); | 4222 ASSERT(args.length() == 3); |
| 4213 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 4223 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
| 4214 CONVERT_ARG_HANDLE_CHECKED(String, search, 1); | 4224 CONVERT_ARG_HANDLE_CHECKED(String, search, 1); |
| 4215 CONVERT_ARG_HANDLE_CHECKED(String, replace, 2); | 4225 CONVERT_ARG_HANDLE_CHECKED(String, replace, 2); |
| 4216 | 4226 |
| 4217 // If the cons string tree is too deep, we simply abort the recursion and | 4227 // If the cons string tree is too deep, we simply abort the recursion and |
| 4218 // retry with a flattened subject string. | 4228 // retry with a flattened subject string. |
| 4219 const int kRecursionLimit = 0x1000; | 4229 const int kRecursionLimit = 0x1000; |
| 4220 bool found = false; | 4230 bool found = false; |
| 4221 Handle<String> result = StringReplaceOneCharWithString(isolate, | 4231 Handle<String> result = StringReplaceOneCharWithString(isolate, |
| 4222 subject, | 4232 subject, |
| 4223 search, | 4233 search, |
| 4224 replace, | 4234 replace, |
| 4225 &found, | 4235 &found, |
| 4226 kRecursionLimit); | 4236 kRecursionLimit); |
| 4227 if (!result.is_null()) return *result; | 4237 if (!result.is_null()) return *result; |
| 4238 if (isolate->has_pending_exception()) return Failure::Exception(); |
| 4228 return *StringReplaceOneCharWithString(isolate, | 4239 return *StringReplaceOneCharWithString(isolate, |
| 4229 FlattenGetString(subject), | 4240 FlattenGetString(subject), |
| 4230 search, | 4241 search, |
| 4231 replace, | 4242 replace, |
| 4232 &found, | 4243 &found, |
| 4233 kRecursionLimit); | 4244 kRecursionLimit); |
| 4234 } | 4245 } |
| 4235 | 4246 |
| 4236 | 4247 |
| 4237 // Perform string match of pattern on subject, starting at start index. | 4248 // Perform string match of pattern on subject, starting at start index. |
| (...skipping 1980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6218 | 6229 |
| 6219 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { | 6230 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { |
| 6220 HandleScope scope(isolate); | 6231 HandleScope scope(isolate); |
| 6221 ASSERT(args.length() == 1); | 6232 ASSERT(args.length() == 1); |
| 6222 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); | 6233 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); |
| 6223 Handle<String> string = FlattenGetString(source); | 6234 Handle<String> string = FlattenGetString(source); |
| 6224 ASSERT(string->IsFlat()); | 6235 ASSERT(string->IsFlat()); |
| 6225 Handle<String> result = string->IsOneByteRepresentationUnderneath() | 6236 Handle<String> result = string->IsOneByteRepresentationUnderneath() |
| 6226 ? URIEscape::Escape<uint8_t>(isolate, source) | 6237 ? URIEscape::Escape<uint8_t>(isolate, source) |
| 6227 : URIEscape::Escape<uc16>(isolate, source); | 6238 : URIEscape::Escape<uc16>(isolate, source); |
| 6228 if (result.is_null()) return Failure::OutOfMemoryException(0x12); | 6239 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 6229 return *result; | 6240 return *result; |
| 6230 } | 6241 } |
| 6231 | 6242 |
| 6232 | 6243 |
| 6233 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) { | 6244 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) { |
| 6234 HandleScope scope(isolate); | 6245 HandleScope scope(isolate); |
| 6235 ASSERT(args.length() == 1); | 6246 ASSERT(args.length() == 1); |
| 6236 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); | 6247 CONVERT_ARG_HANDLE_CHECKED(String, source, 0); |
| 6237 Handle<String> string = FlattenGetString(source); | 6248 Handle<String> string = FlattenGetString(source); |
| 6238 ASSERT(string->IsFlat()); | 6249 ASSERT(string->IsFlat()); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6352 while (stream.HasMore()) { | 6363 while (stream.HasMore()) { |
| 6353 current = stream.GetNext(); | 6364 current = stream.GetNext(); |
| 6354 found_yuml |= (current == yuml_code); | 6365 found_yuml |= (current == yuml_code); |
| 6355 // NOTE: we use 0 as the next character here because, while | 6366 // NOTE: we use 0 as the next character here because, while |
| 6356 // the next character may affect what a character converts to, | 6367 // the next character may affect what a character converts to, |
| 6357 // it does not in any case affect the length of what it convert | 6368 // it does not in any case affect the length of what it convert |
| 6358 // to. | 6369 // to. |
| 6359 int char_length = mapping->get(current, 0, chars); | 6370 int char_length = mapping->get(current, 0, chars); |
| 6360 if (char_length == 0) char_length = 1; | 6371 if (char_length == 0) char_length = 1; |
| 6361 current_length += char_length; | 6372 current_length += char_length; |
| 6362 if (current_length > Smi::kMaxValue) { | 6373 if (current_length > String::kMaxLength) { |
| 6363 isolate->context()->mark_out_of_memory(); | 6374 return isolate->ThrowInvalidStringLength(); |
| 6364 return Failure::OutOfMemoryException(0x13); | |
| 6365 } | 6375 } |
| 6366 } | 6376 } |
| 6367 // Try again with the real length. Return signed if we need | 6377 // Try again with the real length. Return signed if we need |
| 6368 // to allocate a two-byte string for y-umlaut to uppercase. | 6378 // to allocate a two-byte string for y-umlaut to uppercase. |
| 6369 return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length) | 6379 return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length) |
| 6370 : Smi::FromInt(current_length); | 6380 : Smi::FromInt(current_length); |
| 6371 } else { | 6381 } else { |
| 6372 for (int j = 0; j < char_length; j++) { | 6382 for (int j = 0; j < char_length; j++) { |
| 6373 result->Set(i, chars[j]); | 6383 result->Set(i, chars[j]); |
| 6374 i++; | 6384 i++; |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7009 return isolate->heap()->NumberFromInt32(x * y); | 7019 return isolate->heap()->NumberFromInt32(x * y); |
| 7010 } | 7020 } |
| 7011 | 7021 |
| 7012 | 7022 |
| 7013 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) { | 7023 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) { |
| 7014 HandleScope scope(isolate); | 7024 HandleScope scope(isolate); |
| 7015 ASSERT(args.length() == 2); | 7025 ASSERT(args.length() == 2); |
| 7016 CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); | 7026 CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); |
| 7017 CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); | 7027 CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); |
| 7018 isolate->counters()->string_add_runtime()->Increment(); | 7028 isolate->counters()->string_add_runtime()->Increment(); |
| 7019 return *isolate->factory()->NewConsString(str1, str2); | 7029 Handle<String> result = isolate->factory()->NewConsString(str1, str2); |
| 7030 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 7031 return *result; |
| 7020 } | 7032 } |
| 7021 | 7033 |
| 7022 | 7034 |
| 7023 template <typename sinkchar> | 7035 template <typename sinkchar> |
| 7024 static inline void StringBuilderConcatHelper(String* special, | 7036 static inline void StringBuilderConcatHelper(String* special, |
| 7025 sinkchar* sink, | 7037 sinkchar* sink, |
| 7026 FixedArray* fixed_array, | 7038 FixedArray* fixed_array, |
| 7027 int array_length) { | 7039 int array_length) { |
| 7028 int position = 0; | 7040 int position = 0; |
| 7029 for (int i = 0; i < array_length; i++) { | 7041 for (int i = 0; i < array_length; i++) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 7056 position += element_length; | 7068 position += element_length; |
| 7057 } | 7069 } |
| 7058 } | 7070 } |
| 7059 } | 7071 } |
| 7060 | 7072 |
| 7061 | 7073 |
| 7062 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { | 7074 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
| 7063 HandleScope scope(isolate); | 7075 HandleScope scope(isolate); |
| 7064 ASSERT(args.length() == 3); | 7076 ASSERT(args.length() == 3); |
| 7065 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); | 7077 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
| 7066 if (!args[1]->IsSmi()) { | 7078 if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength(); |
| 7067 isolate->context()->mark_out_of_memory(); | |
| 7068 return Failure::OutOfMemoryException(0x14); | |
| 7069 } | |
| 7070 int array_length = args.smi_at(1); | 7079 int array_length = args.smi_at(1); |
| 7071 CONVERT_ARG_HANDLE_CHECKED(String, special, 2); | 7080 CONVERT_ARG_HANDLE_CHECKED(String, special, 2); |
| 7072 | 7081 |
| 7073 // This assumption is used by the slice encoding in one or two smis. | 7082 // This assumption is used by the slice encoding in one or two smis. |
| 7074 ASSERT(Smi::kMaxValue >= String::kMaxLength); | 7083 ASSERT(Smi::kMaxValue >= String::kMaxLength); |
| 7075 | 7084 |
| 7076 JSObject::EnsureCanContainHeapObjectElements(array); | 7085 JSObject::EnsureCanContainHeapObjectElements(array); |
| 7077 | 7086 |
| 7078 int special_length = special->length(); | 7087 int special_length = special->length(); |
| 7079 if (!array->HasFastObjectElements()) { | 7088 if (!array->HasFastObjectElements()) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7133 int element_length = element->length(); | 7142 int element_length = element->length(); |
| 7134 increment = element_length; | 7143 increment = element_length; |
| 7135 if (one_byte && !element->HasOnlyOneByteChars()) { | 7144 if (one_byte && !element->HasOnlyOneByteChars()) { |
| 7136 one_byte = false; | 7145 one_byte = false; |
| 7137 } | 7146 } |
| 7138 } else { | 7147 } else { |
| 7139 ASSERT(!elt->IsTheHole()); | 7148 ASSERT(!elt->IsTheHole()); |
| 7140 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 7149 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
| 7141 } | 7150 } |
| 7142 if (increment > String::kMaxLength - position) { | 7151 if (increment > String::kMaxLength - position) { |
| 7143 isolate->context()->mark_out_of_memory(); | 7152 return isolate->ThrowInvalidStringLength(); |
| 7144 return Failure::OutOfMemoryException(0x15); | |
| 7145 } | 7153 } |
| 7146 position += increment; | 7154 position += increment; |
| 7147 } | 7155 } |
| 7148 | 7156 |
| 7149 int length = position; | 7157 int length = position; |
| 7150 Object* object; | 7158 Object* object; |
| 7151 | 7159 |
| 7152 if (one_byte) { | 7160 if (one_byte) { |
| 7153 { MaybeObject* maybe_object = | 7161 { MaybeObject* maybe_object = |
| 7154 isolate->heap()->AllocateRawOneByteString(length); | 7162 isolate->heap()->AllocateRawOneByteString(length); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7172 array_length); | 7180 array_length); |
| 7173 return answer; | 7181 return answer; |
| 7174 } | 7182 } |
| 7175 } | 7183 } |
| 7176 | 7184 |
| 7177 | 7185 |
| 7178 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { | 7186 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
| 7179 SealHandleScope shs(isolate); | 7187 SealHandleScope shs(isolate); |
| 7180 ASSERT(args.length() == 3); | 7188 ASSERT(args.length() == 3); |
| 7181 CONVERT_ARG_CHECKED(JSArray, array, 0); | 7189 CONVERT_ARG_CHECKED(JSArray, array, 0); |
| 7182 if (!args[1]->IsSmi()) { | 7190 if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength(); |
| 7183 isolate->context()->mark_out_of_memory(); | |
| 7184 return Failure::OutOfMemoryException(0x16); | |
| 7185 } | |
| 7186 int array_length = args.smi_at(1); | 7191 int array_length = args.smi_at(1); |
| 7187 CONVERT_ARG_CHECKED(String, separator, 2); | 7192 CONVERT_ARG_CHECKED(String, separator, 2); |
| 7188 | 7193 |
| 7189 if (!array->HasFastObjectElements()) { | 7194 if (!array->HasFastObjectElements()) { |
| 7190 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 7195 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
| 7191 } | 7196 } |
| 7192 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 7197 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| 7193 if (fixed_array->length() < array_length) { | 7198 if (fixed_array->length() < array_length) { |
| 7194 array_length = fixed_array->length(); | 7199 array_length = fixed_array->length(); |
| 7195 } | 7200 } |
| 7196 | 7201 |
| 7197 if (array_length == 0) { | 7202 if (array_length == 0) { |
| 7198 return isolate->heap()->empty_string(); | 7203 return isolate->heap()->empty_string(); |
| 7199 } else if (array_length == 1) { | 7204 } else if (array_length == 1) { |
| 7200 Object* first = fixed_array->get(0); | 7205 Object* first = fixed_array->get(0); |
| 7201 if (first->IsString()) return first; | 7206 if (first->IsString()) return first; |
| 7202 } | 7207 } |
| 7203 | 7208 |
| 7204 int separator_length = separator->length(); | 7209 int separator_length = separator->length(); |
| 7205 int max_nof_separators = | 7210 int max_nof_separators = |
| 7206 (String::kMaxLength + separator_length - 1) / separator_length; | 7211 (String::kMaxLength + separator_length - 1) / separator_length; |
| 7207 if (max_nof_separators < (array_length - 1)) { | 7212 if (max_nof_separators < (array_length - 1)) { |
| 7208 isolate->context()->mark_out_of_memory(); | 7213 return isolate->ThrowInvalidStringLength(); |
| 7209 return Failure::OutOfMemoryException(0x17); | |
| 7210 } | 7214 } |
| 7211 int length = (array_length - 1) * separator_length; | 7215 int length = (array_length - 1) * separator_length; |
| 7212 for (int i = 0; i < array_length; i++) { | 7216 for (int i = 0; i < array_length; i++) { |
| 7213 Object* element_obj = fixed_array->get(i); | 7217 Object* element_obj = fixed_array->get(i); |
| 7214 if (!element_obj->IsString()) { | 7218 if (!element_obj->IsString()) { |
| 7215 // TODO(1161): handle this case. | 7219 // TODO(1161): handle this case. |
| 7216 return isolate->Throw(isolate->heap()->illegal_argument_string()); | 7220 return isolate->Throw(isolate->heap()->illegal_argument_string()); |
| 7217 } | 7221 } |
| 7218 String* element = String::cast(element_obj); | 7222 String* element = String::cast(element_obj); |
| 7219 int increment = element->length(); | 7223 int increment = element->length(); |
| 7220 if (increment > String::kMaxLength - length) { | 7224 if (increment > String::kMaxLength - length) { |
| 7221 isolate->context()->mark_out_of_memory(); | 7225 return isolate->ThrowInvalidStringLength(); |
| 7222 return Failure::OutOfMemoryException(0x18); | |
| 7223 } | 7226 } |
| 7224 length += increment; | 7227 length += increment; |
| 7225 } | 7228 } |
| 7226 | 7229 |
| 7227 Object* object; | 7230 Object* object; |
| 7228 { MaybeObject* maybe_object = | 7231 { MaybeObject* maybe_object = |
| 7229 isolate->heap()->AllocateRawTwoByteString(length); | 7232 isolate->heap()->AllocateRawTwoByteString(length); |
| 7230 if (!maybe_object->ToObject(&object)) return maybe_object; | 7233 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 7231 } | 7234 } |
| 7232 SeqTwoByteString* answer = SeqTwoByteString::cast(object); | 7235 SeqTwoByteString* answer = SeqTwoByteString::cast(object); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7350 // Nonempty separator and at least 2^31-1 separators necessary | 7353 // Nonempty separator and at least 2^31-1 separators necessary |
| 7351 // means that the string is too large to create. | 7354 // means that the string is too large to create. |
| 7352 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); | 7355 STATIC_ASSERT(String::kMaxLength < 0x7fffffff); |
| 7353 overflow = true; | 7356 overflow = true; |
| 7354 } | 7357 } |
| 7355 } | 7358 } |
| 7356 if (overflow) { | 7359 if (overflow) { |
| 7357 // Throw an exception if the resulting string is too large. See | 7360 // Throw an exception if the resulting string is too large. See |
| 7358 // https://code.google.com/p/chromium/issues/detail?id=336820 | 7361 // https://code.google.com/p/chromium/issues/detail?id=336820 |
| 7359 // for details. | 7362 // for details. |
| 7360 return isolate->Throw(*isolate->factory()-> | 7363 return isolate->ThrowInvalidStringLength(); |
| 7361 NewRangeError("invalid_string_length", | |
| 7362 HandleVector<Object>(NULL, 0))); | |
| 7363 } | 7364 } |
| 7364 | 7365 |
| 7365 if (is_ascii) { | 7366 if (is_ascii) { |
| 7366 MaybeObject* result_allocation = | 7367 MaybeObject* result_allocation = |
| 7367 isolate->heap()->AllocateRawOneByteString(string_length); | 7368 isolate->heap()->AllocateRawOneByteString(string_length); |
| 7368 if (result_allocation->IsFailure()) return result_allocation; | 7369 if (result_allocation->IsFailure()) return result_allocation; |
| 7369 SeqOneByteString* result_string = | 7370 SeqOneByteString* result_string = |
| 7370 SeqOneByteString::cast(result_allocation->ToObjectUnchecked()); | 7371 SeqOneByteString::cast(result_allocation->ToObjectUnchecked()); |
| 7371 JoinSparseArrayWithSeparator<uint8_t>(elements, | 7372 JoinSparseArrayWithSeparator<uint8_t>(elements, |
| 7372 elements_length, | 7373 elements_length, |
| (...skipping 7666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15039 // Handle last resort GC and make sure to allow future allocations | 15040 // Handle last resort GC and make sure to allow future allocations |
| 15040 // to grow the heap without causing GCs (if possible). | 15041 // to grow the heap without causing GCs (if possible). |
| 15041 isolate->counters()->gc_last_resort_from_js()->Increment(); | 15042 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 15042 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 15043 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 15043 "Runtime::PerformGC"); | 15044 "Runtime::PerformGC"); |
| 15044 } | 15045 } |
| 15045 } | 15046 } |
| 15046 | 15047 |
| 15047 | 15048 |
| 15048 } } // namespace v8::internal | 15049 } } // namespace v8::internal |
| OLD | NEW |