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

Side by Side Diff: src/runtime.cc

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