MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
PretenureFlag pretenure) {
int length = string.length();
- if (length == 1) {
- return LookupSingleCharacterStringFromCode(string[0]);
- }
+ if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
Handle<SeqOneByteString> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate(),
// since UTF8 is backwards compatible with ASCII.
return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure);
}
+
// Non-ASCII and we need to decode.
- CALL_HEAP_FUNCTION(
- isolate(),
- isolate()->heap()->AllocateStringFromUtf8Slow(string,
- non_ascii_start,
- pretenure),
+ Access<UnicodeCache::Utf8Decoder>
+ 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<SeqTwoByteString> 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<String> Factory::NewStringFromTwoByte(Vector<const uc16> 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<SeqOneByteString> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate(),
+ result,
+ NewRawOneByteString(length, pretenure),
+ String);
+ CopyChars(result->GetChars(), start, length);
+ return result;
+ } else {
+ Handle<SeqTwoByteString> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate(),
+ result,
+ NewRawTwoByteString(length, pretenure),
+ String);
+ CopyChars(result->GetChars(), start, length);
+ return result;
+ }
}
MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
int length, PretenureFlag pretenure) {
+ if (length > String::kMaxLength || length < 0) {
+ return isolate()->Throw<SeqOneByteString>(NewInvalidStringLengthError());
+ }
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateRawOneByteString(length, pretenure),
MaybeHandle<SeqTwoByteString> Factory::NewRawTwoByteString(
int length, PretenureFlag pretenure) {
+ if (length > String::kMaxLength || length < 0) {
+ return isolate()->Throw<SeqTwoByteString>(NewInvalidStringLengthError());
+ }
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateRawTwoByteString(length, pretenure),
const ExternalAsciiString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
- isolate()->ThrowInvalidStringLength();
- return MaybeHandle<String>();
+ return isolate()->Throw<String>(NewInvalidStringLengthError());
}
Handle<Map> map = external_ascii_string_map();
const ExternalTwoByteString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
- isolate()->ThrowInvalidStringLength();
- return MaybeHandle<String>();
+ return isolate()->Throw<String>(NewInvalidStringLengthError());
}
// For small strings we check whether the resource contains only
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<String> NewStringFromAscii(
Vector<const char> str,
AllocationResult Heap::AllocateOneByteInternalizedString(
Vector<const uint8_t> 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());
AllocationResult Heap::AllocateTwoByteInternalizedString(Vector<const uc16> 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());
// 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; \
}
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; \
}
-AllocationResult Heap::AllocateStringFromUtf8Slow(Vector<const char> 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<UnicodeCache::Utf8Decoder>
- 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<const uc16> 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<const char> vector,
uint8_t* chars,
int len) {
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);
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);
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);
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<const char> str,
- int non_ascii_start,
- PretenureFlag pretenure = NOT_TENURED);
- MUST_USE_RESULT AllocationResult AllocateStringFromTwoByte(
- Vector<const uc16> str,
- PretenureFlag pretenure = NOT_TENURED);
-
bool CreateInitialMaps();
void CreateInitialObjects();