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 3345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3356 | 3356 |
3357 class ReplacementStringBuilder { | 3357 class ReplacementStringBuilder { |
3358 public: | 3358 public: |
3359 ReplacementStringBuilder(Heap* heap, | 3359 ReplacementStringBuilder(Heap* heap, |
3360 Handle<String> subject, | 3360 Handle<String> subject, |
3361 int estimated_part_count) | 3361 int estimated_part_count) |
3362 : heap_(heap), | 3362 : heap_(heap), |
3363 array_builder_(heap->isolate(), estimated_part_count), | 3363 array_builder_(heap->isolate(), estimated_part_count), |
3364 subject_(subject), | 3364 subject_(subject), |
3365 character_count_(0), | 3365 character_count_(0), |
3366 is_ascii_(subject->IsOneByteRepresentation()), | 3366 is_ascii_(subject->IsOneByteRepresentation()) { |
3367 overflowed_(false) { | |
3368 // Require a non-zero initial size. Ensures that doubling the size to | 3367 // Require a non-zero initial size. Ensures that doubling the size to |
3369 // extend the array will work. | 3368 // extend the array will work. |
3370 ASSERT(estimated_part_count > 0); | 3369 ASSERT(estimated_part_count > 0); |
3371 } | 3370 } |
3372 | 3371 |
3373 static inline void AddSubjectSlice(FixedArrayBuilder* builder, | 3372 static inline void AddSubjectSlice(FixedArrayBuilder* builder, |
3374 int from, | 3373 int from, |
3375 int to) { | 3374 int to) { |
3376 ASSERT(from >= 0); | 3375 ASSERT(from >= 0); |
3377 int length = to - from; | 3376 int length = to - from; |
(...skipping 27 matching lines...) Expand all Loading... |
3405 ASSERT(length > 0); | 3404 ASSERT(length > 0); |
3406 AddElement(*string); | 3405 AddElement(*string); |
3407 if (!string->IsOneByteRepresentation()) { | 3406 if (!string->IsOneByteRepresentation()) { |
3408 is_ascii_ = false; | 3407 is_ascii_ = false; |
3409 } | 3408 } |
3410 IncrementCharacterCount(length); | 3409 IncrementCharacterCount(length); |
3411 } | 3410 } |
3412 | 3411 |
3413 | 3412 |
3414 Handle<String> ToString() { | 3413 Handle<String> ToString() { |
3415 if (overflowed_) { | |
3416 heap_->isolate()->ThrowInvalidStringLength(); | |
3417 return Handle<String>(); | |
3418 } | |
3419 | |
3420 if (array_builder_.length() == 0) { | 3414 if (array_builder_.length() == 0) { |
3421 return heap_->isolate()->factory()->empty_string(); | 3415 return heap_->isolate()->factory()->empty_string(); |
3422 } | 3416 } |
3423 | 3417 |
3424 Handle<String> joined_string; | 3418 Handle<String> joined_string; |
3425 if (is_ascii_) { | 3419 if (is_ascii_) { |
3426 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); | 3420 Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); |
| 3421 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>()); |
3427 DisallowHeapAllocation no_gc; | 3422 DisallowHeapAllocation no_gc; |
3428 uint8_t* char_buffer = seq->GetChars(); | 3423 uint8_t* char_buffer = seq->GetChars(); |
3429 StringBuilderConcatHelper(*subject_, | 3424 StringBuilderConcatHelper(*subject_, |
3430 char_buffer, | 3425 char_buffer, |
3431 *array_builder_.array(), | 3426 *array_builder_.array(), |
3432 array_builder_.length()); | 3427 array_builder_.length()); |
3433 joined_string = Handle<String>::cast(seq); | 3428 joined_string = Handle<String>::cast(seq); |
3434 } else { | 3429 } else { |
3435 // Non-ASCII. | 3430 // Non-ASCII. |
3436 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); | 3431 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); |
| 3432 RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>()); |
3437 DisallowHeapAllocation no_gc; | 3433 DisallowHeapAllocation no_gc; |
3438 uc16* char_buffer = seq->GetChars(); | 3434 uc16* char_buffer = seq->GetChars(); |
3439 StringBuilderConcatHelper(*subject_, | 3435 StringBuilderConcatHelper(*subject_, |
3440 char_buffer, | 3436 char_buffer, |
3441 *array_builder_.array(), | 3437 *array_builder_.array(), |
3442 array_builder_.length()); | 3438 array_builder_.length()); |
3443 joined_string = Handle<String>::cast(seq); | 3439 joined_string = Handle<String>::cast(seq); |
3444 } | 3440 } |
3445 return joined_string; | 3441 return joined_string; |
3446 } | 3442 } |
3447 | 3443 |
3448 | 3444 |
3449 void IncrementCharacterCount(int by) { | 3445 void IncrementCharacterCount(int by) { |
3450 if (character_count_ > String::kMaxLength - by) { | 3446 if (character_count_ > String::kMaxLength - by) { |
3451 overflowed_ = true; | 3447 STATIC_ASSERT(String::kMaxLength < kMaxInt); |
| 3448 character_count_ = kMaxInt; |
| 3449 } else { |
| 3450 character_count_ += by; |
3452 } | 3451 } |
3453 character_count_ += by; | |
3454 } | 3452 } |
3455 | 3453 |
3456 private: | 3454 private: |
3457 Handle<SeqOneByteString> NewRawOneByteString(int length) { | 3455 Handle<SeqOneByteString> NewRawOneByteString(int length) { |
3458 return heap_->isolate()->factory()->NewRawOneByteString(length); | 3456 return heap_->isolate()->factory()->NewRawOneByteString(length); |
3459 } | 3457 } |
3460 | 3458 |
3461 | 3459 |
3462 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { | 3460 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { |
3463 return heap_->isolate()->factory()->NewRawTwoByteString(length); | 3461 return heap_->isolate()->factory()->NewRawTwoByteString(length); |
3464 } | 3462 } |
3465 | 3463 |
3466 | 3464 |
3467 void AddElement(Object* element) { | 3465 void AddElement(Object* element) { |
3468 ASSERT(element->IsSmi() || element->IsString()); | 3466 ASSERT(element->IsSmi() || element->IsString()); |
3469 ASSERT(array_builder_.capacity() > array_builder_.length()); | 3467 ASSERT(array_builder_.capacity() > array_builder_.length()); |
3470 array_builder_.Add(element); | 3468 array_builder_.Add(element); |
3471 } | 3469 } |
3472 | 3470 |
3473 Heap* heap_; | 3471 Heap* heap_; |
3474 FixedArrayBuilder array_builder_; | 3472 FixedArrayBuilder array_builder_; |
3475 Handle<String> subject_; | 3473 Handle<String> subject_; |
3476 int character_count_; | 3474 int character_count_; |
3477 bool is_ascii_; | 3475 bool is_ascii_; |
3478 bool overflowed_; | |
3479 }; | 3476 }; |
3480 | 3477 |
3481 | 3478 |
3482 class CompiledReplacement { | 3479 class CompiledReplacement { |
3483 public: | 3480 public: |
3484 explicit CompiledReplacement(Zone* zone) | 3481 explicit CompiledReplacement(Zone* zone) |
3485 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} | 3482 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} |
3486 | 3483 |
3487 // Return whether the replacement is simple. | 3484 // Return whether the replacement is simple. |
3488 bool Compile(Handle<String> replacement, | 3485 bool Compile(Handle<String> replacement, |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3925 | 3922 |
3926 int matches = indices.length(); | 3923 int matches = indices.length(); |
3927 if (matches == 0) return *subject; | 3924 if (matches == 0) return *subject; |
3928 | 3925 |
3929 // Detect integer overflow. | 3926 // Detect integer overflow. |
3930 int64_t result_len_64 = | 3927 int64_t result_len_64 = |
3931 (static_cast<int64_t>(replacement_len) - | 3928 (static_cast<int64_t>(replacement_len) - |
3932 static_cast<int64_t>(pattern_len)) * | 3929 static_cast<int64_t>(pattern_len)) * |
3933 static_cast<int64_t>(matches) + | 3930 static_cast<int64_t>(matches) + |
3934 static_cast<int64_t>(subject_len); | 3931 static_cast<int64_t>(subject_len); |
3935 if (result_len_64 > INT_MAX) { | 3932 int result_len; |
3936 v8::internal::Heap::FatalProcessOutOfMemory("invalid string length", true); | 3933 if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) { |
| 3934 STATIC_ASSERT(String::kMaxLength < kMaxInt); |
| 3935 result_len = kMaxInt; // Provoke exception. |
| 3936 } else { |
| 3937 result_len = static_cast<int>(result_len_64); |
3937 } | 3938 } |
3938 int result_len = static_cast<int>(result_len_64); | |
3939 | 3939 |
3940 int subject_pos = 0; | 3940 int subject_pos = 0; |
3941 int result_pos = 0; | 3941 int result_pos = 0; |
3942 | 3942 |
3943 Handle<ResultSeqString> result; | 3943 Handle<String> result_seq; |
3944 if (ResultSeqString::kHasAsciiEncoding) { | 3944 if (ResultSeqString::kHasAsciiEncoding) { |
3945 result = Handle<ResultSeqString>::cast( | 3945 result_seq = isolate->factory()->NewRawOneByteString(result_len); |
3946 isolate->factory()->NewRawOneByteString(result_len)); | |
3947 } else { | 3946 } else { |
3948 result = Handle<ResultSeqString>::cast( | 3947 result_seq = isolate->factory()->NewRawTwoByteString(result_len); |
3949 isolate->factory()->NewRawTwoByteString(result_len)); | |
3950 } | 3948 } |
| 3949 RETURN_IF_EMPTY_HANDLE(isolate, result_seq); |
| 3950 Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq); |
3951 | 3951 |
3952 for (int i = 0; i < matches; i++) { | 3952 for (int i = 0; i < matches; i++) { |
3953 // Copy non-matched subject content. | 3953 // Copy non-matched subject content. |
3954 if (subject_pos < indices.at(i)) { | 3954 if (subject_pos < indices.at(i)) { |
3955 String::WriteToFlat(*subject, | 3955 String::WriteToFlat(*subject, |
3956 result->GetChars() + result_pos, | 3956 result->GetChars() + result_pos, |
3957 subject_pos, | 3957 subject_pos, |
3958 indices.at(i)); | 3958 indices.at(i)); |
3959 result_pos += indices.at(i) - subject_pos; | 3959 result_pos += indices.at(i) - subject_pos; |
3960 } | 3960 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4120 if (new_length == 0) return isolate->heap()->empty_string(); | 4120 if (new_length == 0) return isolate->heap()->empty_string(); |
4121 | 4121 |
4122 Handle<ResultSeqString> answer; | 4122 Handle<ResultSeqString> answer; |
4123 if (ResultSeqString::kHasAsciiEncoding) { | 4123 if (ResultSeqString::kHasAsciiEncoding) { |
4124 answer = Handle<ResultSeqString>::cast( | 4124 answer = Handle<ResultSeqString>::cast( |
4125 isolate->factory()->NewRawOneByteString(new_length)); | 4125 isolate->factory()->NewRawOneByteString(new_length)); |
4126 } else { | 4126 } else { |
4127 answer = Handle<ResultSeqString>::cast( | 4127 answer = Handle<ResultSeqString>::cast( |
4128 isolate->factory()->NewRawTwoByteString(new_length)); | 4128 isolate->factory()->NewRawTwoByteString(new_length)); |
4129 } | 4129 } |
| 4130 ASSERT(!answer.is_null()); |
4130 | 4131 |
4131 int prev = 0; | 4132 int prev = 0; |
4132 int position = 0; | 4133 int position = 0; |
4133 | 4134 |
4134 do { | 4135 do { |
4135 start = current_match[0]; | 4136 start = current_match[0]; |
4136 end = current_match[1]; | 4137 end = current_match[1]; |
4137 if (prev < start) { | 4138 if (prev < start) { |
4138 // Add substring subject[prev;start] to answer string. | 4139 // Add substring subject[prev;start] to answer string. |
4139 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); | 4140 String::WriteToFlat(*subject, answer->GetChars() + position, prev, start); |
(...skipping 2437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6577 | 6578 |
6578 // Simpler handling of ASCII strings. | 6579 // Simpler handling of ASCII strings. |
6579 // | 6580 // |
6580 // NOTE: This assumes that the upper/lower case of an ASCII | 6581 // NOTE: This assumes that the upper/lower case of an ASCII |
6581 // character is also ASCII. This is currently the case, but it | 6582 // character is also ASCII. This is currently the case, but it |
6582 // might break in the future if we implement more context and locale | 6583 // might break in the future if we implement more context and locale |
6583 // dependent upper/lower conversions. | 6584 // dependent upper/lower conversions. |
6584 if (s->IsOneByteRepresentationUnderneath()) { | 6585 if (s->IsOneByteRepresentationUnderneath()) { |
6585 Handle<SeqOneByteString> result = | 6586 Handle<SeqOneByteString> result = |
6586 isolate->factory()->NewRawOneByteString(length); | 6587 isolate->factory()->NewRawOneByteString(length); |
6587 | 6588 ASSERT(!result.is_null()); // Same length as input. |
6588 DisallowHeapAllocation no_gc; | 6589 DisallowHeapAllocation no_gc; |
6589 String::FlatContent flat_content = s->GetFlatContent(); | 6590 String::FlatContent flat_content = s->GetFlatContent(); |
6590 ASSERT(flat_content.IsFlat()); | 6591 ASSERT(flat_content.IsFlat()); |
6591 bool has_changed_character = false; | 6592 bool has_changed_character = false; |
6592 bool is_ascii = FastAsciiConvert<Converter>( | 6593 bool is_ascii = FastAsciiConvert<Converter>( |
6593 reinterpret_cast<char*>(result->GetChars()), | 6594 reinterpret_cast<char*>(result->GetChars()), |
6594 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), | 6595 reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()), |
6595 length, | 6596 length, |
6596 &has_changed_character); | 6597 &has_changed_character); |
6597 // If not ASCII, we discard the result and take the 2 byte path. | 6598 // If not ASCII, we discard the result and take the 2 byte path. |
6598 if (is_ascii) return has_changed_character ? *result : *s; | 6599 if (is_ascii) return has_changed_character ? *result : *s; |
6599 } | 6600 } |
6600 | 6601 |
6601 Handle<SeqString> result; | 6602 Handle<SeqString> result; |
6602 if (s->IsOneByteRepresentation()) { | 6603 if (s->IsOneByteRepresentation()) { |
6603 result = isolate->factory()->NewRawOneByteString(length); | 6604 result = isolate->factory()->NewRawOneByteString(length); |
6604 } else { | 6605 } else { |
6605 result = isolate->factory()->NewRawTwoByteString(length); | 6606 result = isolate->factory()->NewRawTwoByteString(length); |
6606 } | 6607 } |
| 6608 ASSERT(!result.is_null()); // Same length as input. |
| 6609 |
6607 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); | 6610 MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping); |
6608 Object* answer; | 6611 Object* answer; |
6609 if (!maybe->ToObject(&answer)) return maybe; | 6612 if (!maybe->ToObject(&answer)) return maybe; |
6610 if (answer->IsString()) return answer; | 6613 if (answer->IsString()) return answer; |
6611 | 6614 |
6612 ASSERT(answer->IsSmi()); | 6615 ASSERT(answer->IsSmi()); |
6613 length = Smi::cast(answer)->value(); | 6616 length = Smi::cast(answer)->value(); |
6614 if (s->IsOneByteRepresentation() && length > 0) { | 6617 if (s->IsOneByteRepresentation() && length > 0) { |
6615 result = isolate->factory()->NewRawOneByteString(length); | 6618 result = isolate->factory()->NewRawOneByteString(length); |
6616 } else { | 6619 } else { |
6617 if (length < 0) length = -length; | 6620 if (length < 0) length = -length; |
6618 result = isolate->factory()->NewRawTwoByteString(length); | 6621 result = isolate->factory()->NewRawTwoByteString(length); |
6619 } | 6622 } |
| 6623 RETURN_IF_EMPTY_HANDLE(isolate, result); |
6620 return ConvertCaseHelper(isolate, *s, *result, length, mapping); | 6624 return ConvertCaseHelper(isolate, *s, *result, length, mapping); |
6621 } | 6625 } |
6622 | 6626 |
6623 | 6627 |
6624 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { | 6628 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) { |
6625 return ConvertCase( | 6629 return ConvertCase( |
6626 args, isolate, isolate->runtime_state()->to_lower_mapping()); | 6630 args, isolate, isolate->runtime_state()->to_lower_mapping()); |
6627 } | 6631 } |
6628 | 6632 |
6629 | 6633 |
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7254 if (max_nof_separators < (array_length - 1)) { | 7258 if (max_nof_separators < (array_length - 1)) { |
7255 return isolate->ThrowInvalidStringLength(); | 7259 return isolate->ThrowInvalidStringLength(); |
7256 } | 7260 } |
7257 int length = (array_length - 1) * separator_length; | 7261 int length = (array_length - 1) * separator_length; |
7258 for (int i = 0; i < array_length; i++) { | 7262 for (int i = 0; i < array_length; i++) { |
7259 Object* element_obj = fixed_array->get(i); | 7263 Object* element_obj = fixed_array->get(i); |
7260 RUNTIME_ASSERT(element_obj->IsString()); | 7264 RUNTIME_ASSERT(element_obj->IsString()); |
7261 String* element = String::cast(element_obj); | 7265 String* element = String::cast(element_obj); |
7262 int increment = element->length(); | 7266 int increment = element->length(); |
7263 if (increment > String::kMaxLength - length) { | 7267 if (increment > String::kMaxLength - length) { |
7264 return isolate->ThrowInvalidStringLength(); | 7268 STATIC_ASSERT(String::kMaxLength < kMaxInt); |
| 7269 length = kMaxInt; // Provoke exception; |
| 7270 break; |
7265 } | 7271 } |
7266 length += increment; | 7272 length += increment; |
7267 } | 7273 } |
7268 | 7274 |
7269 Handle<SeqTwoByteString> answer = | 7275 Handle<SeqTwoByteString> answer = |
7270 isolate->factory()->NewRawTwoByteString(length); | 7276 isolate->factory()->NewRawTwoByteString(length); |
| 7277 RETURN_IF_EMPTY_HANDLE(isolate, answer); |
7271 | 7278 |
7272 DisallowHeapAllocation no_gc; | 7279 DisallowHeapAllocation no_gc; |
7273 | 7280 |
7274 uc16* sink = answer->GetChars(); | 7281 uc16* sink = answer->GetChars(); |
7275 #ifdef DEBUG | 7282 #ifdef DEBUG |
7276 uc16* end = sink + length; | 7283 uc16* end = sink + length; |
7277 #endif | 7284 #endif |
7278 | 7285 |
7279 String* first = String::cast(fixed_array->get(0)); | 7286 String* first = String::cast(fixed_array->get(0)); |
7280 String* seperator_raw = *separator; | 7287 String* seperator_raw = *separator; |
(...skipping 2224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9505 "not_date_object", HandleVector<Object>(NULL, 0))); | 9512 "not_date_object", HandleVector<Object>(NULL, 0))); |
9506 } | 9513 } |
9507 | 9514 |
9508 | 9515 |
9509 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { | 9516 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) { |
9510 HandleScope scope(isolate); | 9517 HandleScope scope(isolate); |
9511 ASSERT(args.length() == 1); | 9518 ASSERT(args.length() == 1); |
9512 CONVERT_SMI_ARG_CHECKED(message_id, 0); | 9519 CONVERT_SMI_ARG_CHECKED(message_id, 0); |
9513 const char* message = GetBailoutReason( | 9520 const char* message = GetBailoutReason( |
9514 static_cast<BailoutReason>(message_id)); | 9521 static_cast<BailoutReason>(message_id)); |
9515 Handle<Name> message_handle = | 9522 Handle<String> message_handle = |
9516 isolate->factory()->NewStringFromAscii(CStrVector(message)); | 9523 isolate->factory()->NewStringFromAscii(CStrVector(message)); |
| 9524 RETURN_IF_EMPTY_HANDLE(isolate, message_handle); |
9517 return isolate->Throw(*message_handle); | 9525 return isolate->Throw(*message_handle); |
9518 } | 9526 } |
9519 | 9527 |
9520 | 9528 |
9521 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { | 9529 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { |
9522 SealHandleScope shs(isolate); | 9530 SealHandleScope shs(isolate); |
9523 ASSERT(args.length() == 0); | 9531 ASSERT(args.length() == 0); |
9524 | 9532 |
9525 // First check if this is a real stack overflow. | 9533 // First check if this is a real stack overflow. |
9526 if (isolate->stack_guard()->IsStackOverflow()) { | 9534 if (isolate->stack_guard()->IsStackOverflow()) { |
(...skipping 5571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15098 // Handle last resort GC and make sure to allow future allocations | 15106 // Handle last resort GC and make sure to allow future allocations |
15099 // to grow the heap without causing GCs (if possible). | 15107 // to grow the heap without causing GCs (if possible). |
15100 isolate->counters()->gc_last_resort_from_js()->Increment(); | 15108 isolate->counters()->gc_last_resort_from_js()->Increment(); |
15101 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 15109 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
15102 "Runtime::PerformGC"); | 15110 "Runtime::PerformGC"); |
15103 } | 15111 } |
15104 } | 15112 } |
15105 | 15113 |
15106 | 15114 |
15107 } } // namespace v8::internal | 15115 } } // namespace v8::internal |
OLD | NEW |