Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/runtime.cc

Issue 199853004: Throw exception on invalid string length instead of OOM. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: tests! Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.cc ('k') | src/uri.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/uri.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698