| 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 | 
|---|