Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 762b7a58b9f28fea2dd57f0d6b3f35bdfd7971cd..00bbdfd40bcc7d0a013598ffb8c7ed747c2bf7dd 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -3330,7 +3330,8 @@ class ReplacementStringBuilder { |
array_builder_(heap->isolate(), estimated_part_count), |
subject_(subject), |
character_count_(0), |
- is_ascii_(subject->IsOneByteRepresentation()) { |
+ is_ascii_(subject->IsOneByteRepresentation()), |
+ overflowed_(false) { |
// Require a non-zero initial size. Ensures that doubling the size to |
// extend the array will work. |
ASSERT(estimated_part_count > 0); |
@@ -3378,6 +3379,11 @@ class ReplacementStringBuilder { |
Handle<String> ToString() { |
+ if (overflowed_) { |
+ heap_->isolate()->ThrowInvalidStringLength(); |
+ return Handle<String>(); |
+ } |
+ |
if (array_builder_.length() == 0) { |
return heap_->isolate()->factory()->empty_string(); |
} |
@@ -3409,7 +3415,7 @@ class ReplacementStringBuilder { |
void IncrementCharacterCount(int by) { |
if (character_count_ > String::kMaxLength - by) { |
- V8::FatalProcessOutOfMemory("String.replace result too large."); |
+ overflowed_ = true; |
} |
character_count_ += by; |
} |
@@ -3436,6 +3442,7 @@ class ReplacementStringBuilder { |
Handle<String> subject_; |
int character_count_; |
bool is_ascii_; |
+ bool overflowed_; |
}; |
@@ -4034,7 +4041,9 @@ MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString( |
capture_count, |
global_cache.LastSuccessfulMatch()); |
- return *(builder.ToString()); |
+ Handle<String> result = builder.ToString(); |
+ RETURN_IF_EMPTY_HANDLE(isolate, result); |
+ return *result; |
} |
@@ -4180,8 +4189,8 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate, |
replace, |
found, |
recursion_limit - 1); |
- if (*found) return isolate->factory()->NewConsString(new_first, second); |
if (new_first.is_null()) return new_first; |
+ if (*found) return isolate->factory()->NewConsString(new_first, second); |
Handle<String> new_second = |
StringReplaceOneCharWithString(isolate, |
@@ -4190,8 +4199,8 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate, |
replace, |
found, |
recursion_limit - 1); |
- if (*found) return isolate->factory()->NewConsString(first, new_second); |
if (new_second.is_null()) return new_second; |
+ if (*found) return isolate->factory()->NewConsString(first, new_second); |
return subject; |
} else { |
@@ -4200,6 +4209,7 @@ Handle<String> StringReplaceOneCharWithString(Isolate* isolate, |
*found = true; |
Handle<String> first = isolate->factory()->NewSubString(subject, 0, index); |
Handle<String> cons1 = isolate->factory()->NewConsString(first, replace); |
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>()); |
Handle<String> second = |
isolate->factory()->NewSubString(subject, index + 1, subject->length()); |
return isolate->factory()->NewConsString(cons1, second); |
@@ -4225,6 +4235,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) { |
&found, |
kRecursionLimit); |
if (!result.is_null()) return *result; |
+ if (isolate->has_pending_exception()) return Failure::Exception(); |
return *StringReplaceOneCharWithString(isolate, |
FlattenGetString(subject), |
search, |
@@ -6225,7 +6236,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { |
Handle<String> result = string->IsOneByteRepresentationUnderneath() |
? URIEscape::Escape<uint8_t>(isolate, source) |
: URIEscape::Escape<uc16>(isolate, source); |
- if (result.is_null()) return Failure::OutOfMemoryException(0x12); |
+ RETURN_IF_EMPTY_HANDLE(isolate, result); |
return *result; |
} |
@@ -6359,9 +6370,9 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( |
int char_length = mapping->get(current, 0, chars); |
if (char_length == 0) char_length = 1; |
current_length += char_length; |
- if (current_length > Smi::kMaxValue) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x13); |
+ if (current_length > String::kMaxLength) { |
+ AllowHeapAllocation allocate_error_and_return; |
+ return isolate->ThrowInvalidStringLength(); |
} |
} |
// Try again with the real length. Return signed if we need |
@@ -7016,7 +7027,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) { |
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0); |
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1); |
isolate->counters()->string_add_runtime()->Increment(); |
- return *isolate->factory()->NewConsString(str1, str2); |
+ Handle<String> result = isolate->factory()->NewConsString(str1, str2); |
+ RETURN_IF_EMPTY_HANDLE(isolate, result); |
+ return *result; |
} |
@@ -7063,10 +7076,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
HandleScope scope(isolate); |
ASSERT(args.length() == 3); |
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
- if (!args[1]->IsSmi()) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x14); |
- } |
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength(); |
int array_length = args.smi_at(1); |
CONVERT_ARG_HANDLE_CHECKED(String, special, 2); |
@@ -7140,8 +7150,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
return isolate->Throw(isolate->heap()->illegal_argument_string()); |
} |
if (increment > String::kMaxLength - position) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x15); |
+ return isolate->ThrowInvalidStringLength(); |
} |
position += increment; |
} |
@@ -7176,20 +7185,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
- SealHandleScope shs(isolate); |
+ HandleScope scope(isolate); |
ASSERT(args.length() == 3); |
- CONVERT_ARG_CHECKED(JSArray, array, 0); |
- if (!args[1]->IsSmi()) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x16); |
- } |
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength(); |
int array_length = args.smi_at(1); |
- CONVERT_ARG_CHECKED(String, separator, 2); |
+ CONVERT_ARG_HANDLE_CHECKED(String, separator, 2); |
+ RUNTIME_ASSERT(array->HasFastObjectElements()); |
- if (!array->HasFastObjectElements()) { |
- return isolate->Throw(isolate->heap()->illegal_argument_string()); |
- } |
- FixedArray* fixed_array = FixedArray::cast(array->elements()); |
+ Handle<FixedArray> fixed_array(FixedArray::cast(array->elements())); |
if (fixed_array->length() < array_length) { |
array_length = fixed_array->length(); |
} |
@@ -7198,38 +7202,32 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
return isolate->heap()->empty_string(); |
} else if (array_length == 1) { |
Object* first = fixed_array->get(0); |
- if (first->IsString()) return first; |
+ RUNTIME_ASSERT(first->IsString()); |
+ return first; |
} |
int separator_length = separator->length(); |
int max_nof_separators = |
(String::kMaxLength + separator_length - 1) / separator_length; |
if (max_nof_separators < (array_length - 1)) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x17); |
+ return isolate->ThrowInvalidStringLength(); |
} |
int length = (array_length - 1) * separator_length; |
for (int i = 0; i < array_length; i++) { |
Object* element_obj = fixed_array->get(i); |
- if (!element_obj->IsString()) { |
- // TODO(1161): handle this case. |
- return isolate->Throw(isolate->heap()->illegal_argument_string()); |
- } |
+ RUNTIME_ASSERT(element_obj->IsString()); |
String* element = String::cast(element_obj); |
int increment = element->length(); |
if (increment > String::kMaxLength - length) { |
- isolate->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x18); |
+ return isolate->ThrowInvalidStringLength(); |
} |
length += increment; |
} |
- Object* object; |
- { MaybeObject* maybe_object = |
- isolate->heap()->AllocateRawTwoByteString(length); |
- if (!maybe_object->ToObject(&object)) return maybe_object; |
- } |
- SeqTwoByteString* answer = SeqTwoByteString::cast(object); |
+ Handle<SeqTwoByteString> answer = |
+ isolate->factory()->NewRawTwoByteString(length); |
+ |
+ DisallowHeapAllocation no_gc; |
uc16* sink = answer->GetChars(); |
#ifdef DEBUG |
@@ -7237,13 +7235,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
#endif |
String* first = String::cast(fixed_array->get(0)); |
+ String* seperator_raw = *separator; |
int first_length = first->length(); |
String::WriteToFlat(first, sink, 0, first_length); |
sink += first_length; |
for (int i = 1; i < array_length; i++) { |
ASSERT(sink + separator_length <= end); |
- String::WriteToFlat(separator, sink, 0, separator_length); |
+ String::WriteToFlat(seperator_raw, sink, 0, separator_length); |
sink += separator_length; |
String* element = String::cast(fixed_array->get(i)); |
@@ -7256,7 +7255,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
// Use %_FastAsciiArrayJoin instead. |
ASSERT(!answer->IsOneByteRepresentation()); |
- return answer; |
+ return *answer; |
} |
template <typename Char> |
@@ -7357,9 +7356,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { |
// Throw an exception if the resulting string is too large. See |
// https://code.google.com/p/chromium/issues/detail?id=336820 |
// for details. |
- return isolate->Throw(*isolate->factory()-> |
- NewRangeError("invalid_string_length", |
- HandleVector<Object>(NULL, 0))); |
+ return isolate->ThrowInvalidStringLength(); |
} |
if (is_ascii) { |