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 3326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3337 | 3337 |
3338 class ReplacementStringBuilder { | 3338 class ReplacementStringBuilder { |
3339 public: | 3339 public: |
3340 ReplacementStringBuilder(Heap* heap, | 3340 ReplacementStringBuilder(Heap* heap, |
3341 Handle<String> subject, | 3341 Handle<String> subject, |
3342 int estimated_part_count) | 3342 int estimated_part_count) |
3343 : heap_(heap), | 3343 : heap_(heap), |
3344 array_builder_(heap->isolate(), estimated_part_count), | 3344 array_builder_(heap->isolate(), estimated_part_count), |
3345 subject_(subject), | 3345 subject_(subject), |
3346 character_count_(0), | 3346 character_count_(0), |
3347 is_ascii_(subject->IsOneByteRepresentation()) { | 3347 is_ascii_(subject->IsOneByteRepresentation()), |
| 3348 overflowed_(false) { |
3348 // Require a non-zero initial size. Ensures that doubling the size to | 3349 // Require a non-zero initial size. Ensures that doubling the size to |
3349 // extend the array will work. | 3350 // extend the array will work. |
3350 ASSERT(estimated_part_count > 0); | 3351 ASSERT(estimated_part_count > 0); |
3351 } | 3352 } |
3352 | 3353 |
3353 static inline void AddSubjectSlice(FixedArrayBuilder* builder, | 3354 static inline void AddSubjectSlice(FixedArrayBuilder* builder, |
3354 int from, | 3355 int from, |
3355 int to) { | 3356 int to) { |
3356 ASSERT(from >= 0); | 3357 ASSERT(from >= 0); |
3357 int length = to - from; | 3358 int length = to - from; |
(...skipping 27 matching lines...) Expand all Loading... |
3385 ASSERT(length > 0); | 3386 ASSERT(length > 0); |
3386 AddElement(*string); | 3387 AddElement(*string); |
3387 if (!string->IsOneByteRepresentation()) { | 3388 if (!string->IsOneByteRepresentation()) { |
3388 is_ascii_ = false; | 3389 is_ascii_ = false; |
3389 } | 3390 } |
3390 IncrementCharacterCount(length); | 3391 IncrementCharacterCount(length); |
3391 } | 3392 } |
3392 | 3393 |
3393 | 3394 |
3394 Handle<String> ToString() { | 3395 Handle<String> ToString() { |
| 3396 if (overflowed_) { |
| 3397 heap_->isolate()->ThrowInvalidStringLength(); |
| 3398 return Handle<String>(); |
| 3399 } |
| 3400 |
3395 if (array_builder_.length() == 0) { | 3401 if (array_builder_.length() == 0) { |
3396 return heap_->isolate()->factory()->empty_string(); | 3402 return heap_->isolate()->factory()->empty_string(); |
3397 } | 3403 } |
3398 | 3404 |
3399 Handle<String> joined_string; | 3405 Handle<String> joined_string; |
3400 if (is_ascii_) { | 3406 if (is_ascii_) { |
3401 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); | 3407 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); |
3402 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>()); | |
3403 DisallowHeapAllocation no_gc; | 3408 DisallowHeapAllocation no_gc; |
3404 uint8_t* char_buffer = seq->GetChars(); | 3409 uint8_t* char_buffer = seq->GetChars(); |
3405 StringBuilderConcatHelper(*subject_, | 3410 StringBuilderConcatHelper(*subject_, |
3406 char_buffer, | 3411 char_buffer, |
3407 *array_builder_.array(), | 3412 *array_builder_.array(), |
3408 array_builder_.length()); | 3413 array_builder_.length()); |
3409 joined_string = Handle<String>::cast(seq); | 3414 joined_string = Handle<String>::cast(seq); |
3410 } else { | 3415 } else { |
3411 // Non-ASCII. | 3416 // Non-ASCII. |
3412 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); | 3417 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); |
3413 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>()); | |
3414 DisallowHeapAllocation no_gc; | 3418 DisallowHeapAllocation no_gc; |
3415 uc16* char_buffer = seq->GetChars(); | 3419 uc16* char_buffer = seq->GetChars(); |
3416 StringBuilderConcatHelper(*subject_, | 3420 StringBuilderConcatHelper(*subject_, |
3417 char_buffer, | 3421 char_buffer, |
3418 *array_builder_.array(), | 3422 *array_builder_.array(), |
3419 array_builder_.length()); | 3423 array_builder_.length()); |
3420 joined_string = Handle<String>::cast(seq); | 3424 joined_string = Handle<String>::cast(seq); |
3421 } | 3425 } |
3422 return joined_string; | 3426 return joined_string; |
3423 } | 3427 } |
3424 | 3428 |
3425 | 3429 |
3426 void IncrementCharacterCount(int by) { | 3430 void IncrementCharacterCount(int by) { |
3427 if (character_count_ > String::kMaxLength - by) { | 3431 if (character_count_ > String::kMaxLength - by) { |
3428 STATIC_ASSERT(String::kMaxLength < kMaxInt); | 3432 overflowed_ = true; |
3429 character_count_ = kMaxInt; | |
3430 } else { | |
3431 character_count_ += by; | |
3432 } | 3433 } |
| 3434 character_count_ += by; |
3433 } | 3435 } |
3434 | 3436 |
3435 private: | 3437 private: |
3436 Handle<SeqOneByteString> NewRawOneByteString(int length) { | 3438 Handle<SeqOneByteString> NewRawOneByteString(int length) { |
3437 return heap_->isolate()->factory()->NewRawOneByteString(length); | 3439 return heap_->isolate()->factory()->NewRawOneByteString(length); |
3438 } | 3440 } |
3439 | 3441 |
3440 | 3442 |
3441 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { | 3443 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { |
3442 return heap_->isolate()->factory()->NewRawTwoByteString(length); | 3444 return heap_->isolate()->factory()->NewRawTwoByteString(length); |
3443 } | 3445 } |
3444 | 3446 |
3445 | 3447 |
3446 void AddElement(Object* element) { | 3448 void AddElement(Object* element) { |
3447 ASSERT(element->IsSmi() || element->IsString()); | 3449 ASSERT(element->IsSmi() || element->IsString()); |
3448 ASSERT(array_builder_.capacity() > array_builder_.length()); | 3450 ASSERT(array_builder_.capacity() > array_builder_.length()); |
3449 array_builder_.Add(element); | 3451 array_builder_.Add(element); |
3450 } | 3452 } |
3451 | 3453 |
3452 Heap* heap_; | 3454 Heap* heap_; |
3453 FixedArrayBuilder array_builder_; | 3455 FixedArrayBuilder array_builder_; |
3454 Handle<String> subject_; | 3456 Handle<String> subject_; |
3455 int character_count_; | 3457 int character_count_; |
3456 bool is_ascii_; | 3458 bool is_ascii_; |
| 3459 bool overflowed_; |
3457 }; | 3460 }; |
3458 | 3461 |
3459 | 3462 |
3460 class CompiledReplacement { | 3463 class CompiledReplacement { |
3461 public: | 3464 public: |
3462 explicit CompiledReplacement(Zone* zone) | 3465 explicit CompiledReplacement(Zone* zone) |
3463 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} | 3466 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} |
3464 | 3467 |
3465 // Return whether the replacement is simple. | 3468 // Return whether the replacement is simple. |
3466 bool Compile(Handle<String> replacement, | 3469 bool Compile(Handle<String> replacement, |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 | 3906 |
3904 int matches = indices.length(); | 3907 int matches = indices.length(); |
3905 if (matches == 0) return *subject; | 3908 if (matches == 0) return *subject; |
3906 | 3909 |
3907 // Detect integer overflow. | 3910 // Detect integer overflow. |
3908 int64_t result_len_64 = | 3911 int64_t result_len_64 = |
3909 (static_cast<int64_t>(replacement_len) - | 3912 (static_cast<int64_t>(replacement_len) - |
3910 static_cast<int64_t>(pattern_len)) * | 3913 static_cast<int64_t>(pattern_len)) * |
3911 static_cast<int64_t>(matches) + | 3914 static_cast<int64_t>(matches) + |
3912 static_cast<int64_t>(subject_len); | 3915 static_cast<int64_t>(subject_len); |
3913 int result_len; | 3916 if (result_len_64 > INT_MAX) { |
3914 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) { | 3917 v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true); |
3915 STATIC_ASSERT(String::kMaxLength < kMaxInt); | |
3916 result_len = kMaxInt; // Provoke exception. | |
3917 } else { | |
3918 result_len = static_cast<int>(result_len_64); | |
3919 } | 3918 } |
| 3919 int result_len = static_cast<int>(result_len_64); |
3920 | 3920 |
3921 int subject_pos = 0; | 3921 int subject_pos = 0; |
3922 int result_pos = 0; | 3922 int result_pos = 0; |
3923 | 3923 |
3924 Handle<ResultSeqString> result; | 3924 Handle<ResultSeqString> result; |
3925 if (ResultSeqString::kHasAsciiEncoding) { | 3925 if (ResultSeqString::kHasAsciiEncoding) { |
3926 result = Handle<ResultSeqString>::cast( | 3926 result = Handle<ResultSeqString>::cast( |
3927 isolate->factory()->NewRawOneByteString(result_len)); | 3927 isolate->factory()->NewRawOneByteString(result_len)); |
3928 } else { | 3928 } else { |
3929 result = Handle<ResultSeqString>::cast( | 3929 result = Handle<ResultSeqString>::cast( |
3930 isolate->factory()->NewRawTwoByteString(result_len)); | 3930 isolate->factory()->NewRawTwoByteString(result_len)); |
3931 } | 3931 } |
3932 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
3933 | 3932 |
3934 for (int i = 0; i < matches; i++) { | 3933 for (int i = 0; i < matches; i++) { |
3935 // Copy non-matched subject content. | 3934 // Copy non-matched subject content. |
3936 if (subject_pos < indices.at(i)) { | 3935 if (subject_pos < indices.at(i)) { |
3937 String::WriteToFlat(*subject, | 3936 String::WriteToFlat(*subject, |
3938 result->GetChars() + result_pos, | 3937 result->GetChars() + result_pos, |
3939 subject_pos, | 3938 subject_pos, |
3940 indices.at(i)); | 3939 indices.at(i)); |
3941 result_pos += indices.at(i) - subject_pos; | 3940 result_pos += indices.at(i) - subject_pos; |
3942 } | 3941 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4102 if (new_length == 0) return isolate->heap()->empty_string(); | 4101 if (new_length == 0) return isolate->heap()->empty_string(); |
4103 | 4102 |
4104 Handle<ResultSeqString> answer; | 4103 Handle<ResultSeqString> answer; |
4105 if (ResultSeqString::kHasAsciiEncoding) { | 4104 if (ResultSeqString::kHasAsciiEncoding) { |
4106 answer = Handle<ResultSeqString>::cast( | 4105 answer = Handle<ResultSeqString>::cast( |
4107 isolate->factory()->NewRawOneByteString(new_length)); | 4106 isolate->factory()->NewRawOneByteString(new_length)); |
4108 } else { | 4107 } else { |
4109 answer = Handle<ResultSeqString>::cast( | 4108 answer = Handle<ResultSeqString>::cast( |
4110 isolate->factory()->NewRawTwoByteString(new_length)); | 4109 isolate->factory()->NewRawTwoByteString(new_length)); |
4111 } | 4110 } |
4112 ASSERT(!answer.is_null()); | |
4113 | 4111 |
4114 int prev = 0; | 4112 int prev = 0; |
4115 int position = 0; | 4113 int position = 0; |
4116 | 4114 |
4117 do { | 4115 do { |
4118 start = current_match[0]; | 4116 start = current_match[0]; |
4119 end = current_match[1]; | 4117 end = current_match[1]; |
4120 if (prev < start) { | 4118 if (prev < start) { |
4121 // Add substring subject[prev;start] to answer string. | 4119 // Add substring subject[prev;start] to answer string. |
4122 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); | 4120 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); |
(...skipping 2437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6560 | 6558 |
6561 // Simpler handling of ASCII strings. | 6559 // Simpler handling of ASCII strings. |
6562 // | 6560 // |
6563 // NOTE: This assumes that the upper/lower case of an ASCII | 6561 // NOTE: This assumes that the upper/lower case of an ASCII |
6564 // character is also ASCII. This is currently the case, but it | 6562 // character is also ASCII. This is currently the case, but it |
6565 // might break in the future if we implement more context and locale | 6563 // might break in the future if we implement more context and locale |
6566 // dependent upper/lower conversions. | 6564 // dependent upper/lower conversions. |
6567 if (s->IsOneByteRepresentationUnderneath()) { | 6565 if (s->IsOneByteRepresentationUnderneath()) { |
6568 Handle<SeqOneByteString> result = | 6566 Handle<SeqOneByteString> result = |
6569 isolate->factory()->NewRawOneByteString(length); | 6567 isolate->factory()->NewRawOneByteString(length); |
6570 ASSERT(!result.is_null()); // Same length as input. | 6568 |
6571 DisallowHeapAllocation no_gc; | 6569 DisallowHeapAllocation no_gc; |
6572 String::FlatContent flat_content = s->GetFlatContent(); | 6570 String::FlatContent flat_content = s->GetFlatContent(); |
6573 ASSERT(flat_content.IsFlat()); | 6571 ASSERT(flat_content.IsFlat()); |
6574 bool has_changed_character = false; | 6572 bool has_changed_character = false; |
6575 bool is_ascii = FastAsciiConvert<Converter>( | 6573 bool is_ascii = FastAsciiConvert<Converter>( |
6576 reinterpret_cast<char*>(result->GetChars()), | 6574 reinterpret_cast<char*>(result->GetChars()), |
6577 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), | 6575 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), |
6578 length, | 6576 length, |
6579 &has_changed_character); | 6577 &has_changed_character); |
6580 // If not ASCII, we discard the result and take the 2 byte path. | 6578 // If not ASCII, we discard the result and take the 2 byte path. |
6581 if (is_ascii) return has_changed_character ? *result : *s; | 6579 if (is_ascii) return has_changed_character ? *result : *s; |
6582 } | 6580 } |
6583 | 6581 |
6584 Handle<SeqString> result; | 6582 Handle<SeqString> result; |
6585 if (s->IsOneByteRepresentation()) { | 6583 if (s->IsOneByteRepresentation()) { |
6586 result = isolate->factory()->NewRawOneByteString(length); | 6584 result = isolate->factory()->NewRawOneByteString(length); |
6587 } else { | 6585 } else { |
6588 result = isolate->factory()->NewRawTwoByteString(length); | 6586 result = isolate->factory()->NewRawTwoByteString(length); |
6589 } | 6587 } |
6590 ASSERT(!result.is_null()); // Same length as input. | |
6591 | |
6592 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); | 6588 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); |
6593 Object* answer; | 6589 Object* answer; |
6594 if (!maybe->ToObject(&answer)) return maybe; | 6590 if (!maybe->ToObject(&answer)) return maybe; |
6595 if (answer->IsString()) return answer; | 6591 if (answer->IsString()) return answer; |
6596 | 6592 |
6597 ASSERT(answer->IsSmi()); | 6593 ASSERT(answer->IsSmi()); |
6598 length = Smi::cast(answer)->value(); | 6594 length = Smi::cast(answer)->value(); |
6599 if (s->IsOneByteRepresentation() && length > 0) { | 6595 if (s->IsOneByteRepresentation() && length > 0) { |
6600 result = isolate->factory()->NewRawOneByteString(length); | 6596 result = isolate->factory()->NewRawOneByteString(length); |
6601 } else { | 6597 } else { |
6602 if (length < 0) length = -length; | 6598 if (length < 0) length = -length; |
6603 result = isolate->factory()->NewRawTwoByteString(length); | 6599 result = isolate->factory()->NewRawTwoByteString(length); |
6604 } | 6600 } |
6605 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
6606 return ConvertCaseHelper(isolate, *s, *result, length, mapping); | 6601 return ConvertCaseHelper(isolate, *s, *result, length, mapping); |
6607 } | 6602 } |
6608 | 6603 |
6609 | 6604 |
6610 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { | 6605 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { |
6611 return ConvertCase( | 6606 return ConvertCase( |
6612 args, isolate, isolate->runtime_state()->to_lower_mapping()); | 6607 args, isolate, isolate->runtime_state()->to_lower_mapping()); |
6613 } | 6608 } |
6614 | 6609 |
6615 | 6610 |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7240 if (max_nof_separators < (array_length - 1)) { | 7235 if (max_nof_separators < (array_length - 1)) { |
7241 return isolate->ThrowInvalidStringLength(); | 7236 return isolate->ThrowInvalidStringLength(); |
7242 } | 7237 } |
7243 int length = (array_length - 1) * separator_length; | 7238 int length = (array_length - 1) * separator_length; |
7244 for (int i = 0; i < array_length; i++) { | 7239 for (int i = 0; i < array_length; i++) { |
7245 Object* element_obj = fixed_array->get(i); | 7240 Object* element_obj = fixed_array->get(i); |
7246 RUNTIME_ASSERT(element_obj->IsString()); | 7241 RUNTIME_ASSERT(element_obj->IsString()); |
7247 String* element = String::cast(element_obj); | 7242 String* element = String::cast(element_obj); |
7248 int increment = element->length(); | 7243 int increment = element->length(); |
7249 if (increment > String::kMaxLength - length) { | 7244 if (increment > String::kMaxLength - length) { |
7250 STATIC_ASSERT(String::kMaxLength < kMaxInt); | 7245 return isolate->ThrowInvalidStringLength(); |
7251 length = kMaxInt; // Provoke exception; | |
7252 break; | |
7253 } | 7246 } |
7254 length += increment; | 7247 length += increment; |
7255 } | 7248 } |
7256 | 7249 |
7257 Handle<SeqTwoByteString> answer = | 7250 Handle<SeqTwoByteString> answer = |
7258 isolate->factory()->NewRawTwoByteString(length); | 7251 isolate->factory()->NewRawTwoByteString(length); |
7259 RETURN_IF_EMPTY_HANDLE(isolate, answer); | |
7260 | 7252 |
7261 DisallowHeapAllocation no_gc; | 7253 DisallowHeapAllocation no_gc; |
7262 | 7254 |
7263 uc16* sink = answer->GetChars(); | 7255 uc16* sink = answer->GetChars(); |
7264 #ifdef DEBUG | 7256 #ifdef DEBUG |
7265 uc16* end = sink + length; | 7257 uc16* end = sink + length; |
7266 #endif | 7258 #endif |
7267 | 7259 |
7268 String* first = String::cast(fixed_array->get(0)); | 7260 String* first = String::cast(fixed_array->get(0)); |
7269 String* seperator_raw = *separator; | 7261 String* seperator_raw = *separator; |
(...skipping 2224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9494 "not_date_object", HandleVector<Object>(NULL, 0))); | 9486 "not_date_object", HandleVector<Object>(NULL, 0))); |
9495 } | 9487 } |
9496 | 9488 |
9497 | 9489 |
9498 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { | 9490 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { |
9499 HandleScope scope(isolate); | 9491 HandleScope scope(isolate); |
9500 ASSERT(args.length() == 1); | 9492 ASSERT(args.length() == 1); |
9501 CONVERT_SMI_ARG_CHECKED(message_id, 0); | 9493 CONVERT_SMI_ARG_CHECKED(message_id, 0); |
9502 const char* message = GetBailoutReason( | 9494 const char* message = GetBailoutReason( |
9503 static_cast<BailoutReason>(message_id)); | 9495 static_cast<BailoutReason>(message_id)); |
9504 Handle<String> message_handle = | 9496 Handle<Name> message_handle = |
9505 isolate->factory()->NewStringFromAscii(CStrVector(message)); | 9497 isolate->factory()->NewStringFromAscii(CStrVector(message)); |
9506 RETURN_IF_EMPTY_HANDLE(isolate, message_handle); | |
9507 return isolate->Throw(*message_handle); | 9498 return isolate->Throw(*message_handle); |
9508 } | 9499 } |
9509 | 9500 |
9510 | 9501 |
9511 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { | 9502 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { |
9512 SealHandleScope shs(isolate); | 9503 SealHandleScope shs(isolate); |
9513 ASSERT(args.length() == 0); | 9504 ASSERT(args.length() == 0); |
9514 | 9505 |
9515 // First check if this is a real stack overflow. | 9506 // First check if this is a real stack overflow. |
9516 if (isolate->stack_guard()->IsStackOverflow()) { | 9507 if (isolate->stack_guard()->IsStackOverflow()) { |
(...skipping 5571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15088 // Handle last resort GC and make sure to allow future allocations | 15079 // Handle last resort GC and make sure to allow future allocations |
15089 // to grow the heap without causing GCs (if possible). | 15080 // to grow the heap without causing GCs (if possible). |
15090 isolate->counters()->gc_last_resort_from_js()->Increment(); | 15081 isolate->counters()->gc_last_resort_from_js()->Increment(); |
15091 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 15082 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
15092 "Runtime::PerformGC"); | 15083 "Runtime::PerformGC"); |
15093 } | 15084 } |
15094 } | 15085 } |
15095 | 15086 |
15096 | 15087 |
15097 } } // namespace v8::internal | 15088 } } // namespace v8::internal |
OLD | NEW |