diff --git a/src/factory.cc b/src/factory.cc index 86c314c0db..3d373fbb5b 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -212,9 +212,7 @@ template Handle Factory::InternalizeStringWithKey< MaybeHandle Factory::NewStringFromOneByte(Vector string, PretenureFlag pretenure) { int length = string.length(); - if (length == 1) { - return LookupSingleCharacterStringFromCode(string[0]); - } + if (length == 1) return LookupSingleCharacterStringFromCode(string[0]); Handle result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), @@ -241,22 +239,55 @@ MaybeHandle Factory::NewStringFromUtf8(Vector string, // since UTF8 is backwards compatible with ASCII. return NewStringFromOneByte(Vector::cast(string), pretenure); } + // Non-ASCII and we need to decode. - CALL_HEAP_FUNCTION( - isolate(), - isolate()->heap()->AllocateStringFromUtf8Slow(string, - non_ascii_start, - pretenure), + Access + decoder(isolate()->unicode_cache()->utf8_decoder()); + decoder->Reset(string.start() + non_ascii_start, + length - non_ascii_start); + int utf16_length = decoder->Utf16Length(); + ASSERT(utf16_length > 0); + // Allocate string. + Handle result; + ASSIGN_RETURN_ON_EXCEPTION( + isolate(), result, + NewRawTwoByteString(non_ascii_start + utf16_length, pretenure), String); + // Copy ascii portion. + uint16_t* data = result->GetChars(); + const char* ascii_data = string.start(); + for (int i = 0; i < non_ascii_start; i++) { + *data++ = *ascii_data++; + } + // Now write the remainder. + decoder->WriteUtf16(data, utf16_length); + return result; } MaybeHandle Factory::NewStringFromTwoByte(Vector string, PretenureFlag pretenure) { - CALL_HEAP_FUNCTION( - isolate(), - isolate()->heap()->AllocateStringFromTwoByte(string, pretenure), - String); + int length = string.length(); + const uc16* start = string.start(); + if (String::IsOneByte(start, length)) { + Handle result; + ASSIGN_RETURN_ON_EXCEPTION( + isolate(), + result, + NewRawOneByteString(length, pretenure), + String); + CopyChars(result->GetChars(), start, length); + return result; + } else { + Handle result; + ASSIGN_RETURN_ON_EXCEPTION( + isolate(), + result, + NewRawTwoByteString(length, pretenure), + String); + CopyChars(result->GetChars(), start, length); + return result; + } } @@ -328,6 +359,9 @@ MaybeHandle Factory::InternalizedStringMapForString( MaybeHandle Factory::NewRawOneByteString( int length, PretenureFlag pretenure) { + if (length > String::kMaxLength || length < 0) { + return isolate()->Throw(NewInvalidStringLengthError()); + } CALL_HEAP_FUNCTION( isolate(), isolate()->heap()->AllocateRawOneByteString(length, pretenure), @@ -337,6 +371,9 @@ MaybeHandle Factory::NewRawOneByteString( MaybeHandle Factory::NewRawTwoByteString( int length, PretenureFlag pretenure) { + if (length > String::kMaxLength || length < 0) { + return isolate()->Throw(NewInvalidStringLengthError()); + } CALL_HEAP_FUNCTION( isolate(), isolate()->heap()->AllocateRawTwoByteString(length, pretenure), @@ -586,8 +623,7 @@ MaybeHandle Factory::NewExternalStringFromAscii( const ExternalAsciiString::Resource* resource) { size_t length = resource->length(); if (length > static_cast(String::kMaxLength)) { - isolate()->ThrowInvalidStringLength(); - return MaybeHandle(); + return isolate()->Throw(NewInvalidStringLengthError()); } Handle map = external_ascii_string_map(); @@ -605,8 +641,7 @@ MaybeHandle Factory::NewExternalStringFromTwoByte( const ExternalTwoByteString::Resource* resource) { size_t length = resource->length(); if (length > static_cast(String::kMaxLength)) { - isolate()->ThrowInvalidStringLength(); - return MaybeHandle(); + return isolate()->Throw(NewInvalidStringLengthError()); } // For small strings we check whether the resource contains only diff --git a/src/factory.h b/src/factory.h index 7ef8911d70..e22ea8d323 100644 --- a/src/factory.h +++ b/src/factory.h @@ -122,6 +122,23 @@ class Factory V8_FINAL { OneByteVector(str), pretenure).ToHandleChecked(); } + + // Allocates and fully initializes a String. There are two String + // encodings: ASCII and two byte. One should choose between the three string + // allocation functions based on the encoding of the string buffer used to + // initialized the string. + // - ...FromAscii initializes the string from a buffer that is ASCII + // encoded (it does not check that the buffer is ASCII encoded) and the + // result will be ASCII encoded. + // - ...FromUTF8 initializes the string from a buffer that is UTF-8 + // encoded. If the characters are all single-byte characters, the + // result will be ASCII encoded, otherwise it will converted to two + // byte. + // - ...FromTwoByte initializes the string from a buffer that is two-byte + // encoded. If the characters are all single-byte characters, the + // result will be converted to ASCII, otherwise it will be left as + // two-byte. + // TODO(dcarney): remove this function. MUST_USE_RESULT inline MaybeHandle NewStringFromAscii( Vector str, diff --git a/src/heap-inl.h b/src/heap-inl.h index 64125bc302..2e80452b05 100644 --- a/src/heap-inl.h +++ b/src/heap-inl.h @@ -98,9 +98,7 @@ AllocationResult Heap::AllocateInternalizedStringImpl( AllocationResult Heap::AllocateOneByteInternalizedString( Vector str, uint32_t hash_field) { - if (str.length() > String::kMaxLength) { - return isolate()->ThrowInvalidStringLength(); - } + CHECK_GE(String::kMaxLength, str.length()); // Compute map and object size. Map* map = ascii_internalized_string_map(); int size = SeqOneByteString::SizeFor(str.length()); @@ -131,9 +129,7 @@ AllocationResult Heap::AllocateOneByteInternalizedString( AllocationResult Heap::AllocateTwoByteInternalizedString(Vector str, uint32_t hash_field) { - if (str.length() > String::kMaxLength) { - return isolate()->ThrowInvalidStringLength(); - } + CHECK_GE(String::kMaxLength, str.length()); // Compute map and object size. Map* map = internalized_string_map(); int size = SeqTwoByteString::SizeFor(str.length()); @@ -540,10 +536,9 @@ Isolate* Heap::isolate() { // Warning: Do not use the identifiers __object__, __maybe_object__ or // __scope__ in a call to this macro. -#define RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ - if (!__allocation__.IsRetry()) { \ - __object__ = __allocation__.ToObjectChecked(); \ - if (__object__ == (ISOLATE)->heap()->exception()) { RETURN_EMPTY; } \ +#define RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \ + if (__allocation__.To(&__object__)) { \ + ASSERT(__object__ != (ISOLATE)->heap()->exception()); \ RETURN_VALUE; \ } @@ -551,18 +546,18 @@ Isolate* Heap::isolate() { do { \ AllocationResult __allocation__ = FUNCTION_CALL; \ Object* __object__ = NULL; \ - RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \ (ISOLATE)->heap()->CollectGarbage(__allocation__.RetrySpace(), \ "allocation failure"); \ __allocation__ = FUNCTION_CALL; \ - RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \ (ISOLATE)->counters()->gc_last_resort_from_handles()->Increment(); \ (ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \ { \ AlwaysAllocateScope __scope__(ISOLATE); \ __allocation__ = FUNCTION_CALL; \ } \ - RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ + RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \ /* TODO(1181417): Fix this. */ \ v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \ RETURN_EMPTY; \ diff --git a/src/heap.cc b/src/heap.cc index 7806f0af20..7260e7a27b 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3750,64 +3750,6 @@ AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) { } -AllocationResult Heap::AllocateStringFromUtf8Slow(Vector string, - int non_ascii_start, - PretenureFlag pretenure) { - // Continue counting the number of characters in the UTF-8 string, starting - // from the first non-ascii character or word. - Access - decoder(isolate_->unicode_cache()->utf8_decoder()); - decoder->Reset(string.start() + non_ascii_start, - string.length() - non_ascii_start); - int utf16_length = decoder->Utf16Length(); - ASSERT(utf16_length > 0); - // Allocate string. - HeapObject* result; - { - int chars = non_ascii_start + utf16_length; - AllocationResult allocation = AllocateRawTwoByteString(chars, pretenure); - if (!allocation.To(&result) || result->IsException()) { - return allocation; - } - } - // Copy ascii portion. - uint16_t* data = SeqTwoByteString::cast(result)->GetChars(); - if (non_ascii_start != 0) { - const char* ascii_data = string.start(); - for (int i = 0; i < non_ascii_start; i++) { - *data++ = *ascii_data++; - } - } - // Now write the remainder. - decoder->WriteUtf16(data, utf16_length); - return result; -} - - -AllocationResult Heap::AllocateStringFromTwoByte(Vector string, - PretenureFlag pretenure) { - // Check if the string is an ASCII string. - HeapObject* result; - int length = string.length(); - const uc16* start = string.start(); - - if (String::IsOneByte(start, length)) { - AllocationResult allocation = AllocateRawOneByteString(length, pretenure); - if (!allocation.To(&result) || result->IsException()) { - return allocation; - } - CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length); - } else { // It's not a one byte string. - AllocationResult allocation = AllocateRawTwoByteString(length, pretenure); - if (!allocation.To(&result) || result->IsException()) { - return allocation; - } - CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length); - } - return result; -} - - static inline void WriteOneByteData(Vector vector, uint8_t* chars, int len) { @@ -3864,9 +3806,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl( int size; Map* map; - if (chars < 0 || chars > String::kMaxLength) { - return isolate()->ThrowInvalidStringLength(); - } + ASSERT_LE(0, chars); + ASSERT_GE(String::kMaxLength, chars); if (is_one_byte) { map = ascii_internalized_string_map(); size = SeqOneByteString::SizeFor(chars); @@ -3913,9 +3854,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl( AllocationResult Heap::AllocateRawOneByteString(int length, PretenureFlag pretenure) { - if (length < 0 || length > String::kMaxLength) { - return isolate()->ThrowInvalidStringLength(); - } + ASSERT_LE(0, length); + ASSERT_GE(String::kMaxLength, length); int size = SeqOneByteString::SizeFor(length); ASSERT(size <= SeqOneByteString::kMaxSize); AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure); @@ -3937,9 +3877,8 @@ AllocationResult Heap::AllocateRawOneByteString(int length, AllocationResult Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { - if (length < 0 || length > String::kMaxLength) { - return isolate()->ThrowInvalidStringLength(); - } + ASSERT_LE(0, length); + ASSERT_GE(String::kMaxLength, length); int size = SeqTwoByteString::SizeFor(length); ASSERT(size <= SeqTwoByteString::kMaxSize); AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure); diff --git a/src/heap.h b/src/heap.h index 2671a52101..97de93eab9 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1792,29 +1792,6 @@ class Heap { MUST_USE_RESULT AllocationResult AllocateRawTwoByteString( int length, PretenureFlag pretenure); - // Allocates and fully initializes a String. There are two String - // encodings: ASCII and two byte. One should choose between the three string - // allocation functions based on the encoding of the string buffer used to - // initialized the string. - // - ...FromAscii initializes the string from a buffer that is ASCII - // encoded (it does not check that the buffer is ASCII encoded) and the - // result will be ASCII encoded. - // - ...FromUTF8 initializes the string from a buffer that is UTF-8 - // encoded. If the characters are all single-byte characters, the - // result will be ASCII encoded, otherwise it will converted to two - // byte. - // - ...FromTwoByte initializes the string from a buffer that is two-byte - // encoded. If the characters are all single-byte characters, the - // result will be converted to ASCII, otherwise it will be left as - // two-byte. - MUST_USE_RESULT AllocationResult AllocateStringFromUtf8Slow( - Vector str, - int non_ascii_start, - PretenureFlag pretenure = NOT_TENURED); - MUST_USE_RESULT AllocationResult AllocateStringFromTwoByte( - Vector str, - PretenureFlag pretenure = NOT_TENURED); - bool CreateInitialMaps(); void CreateInitialObjects();