Commit 0be13a77 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Move invalid string length check to the factory.

R=ishell@chromium.org

Review URL: https://codereview.chromium.org/347503003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21886 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1a138034
...@@ -212,9 +212,7 @@ template Handle<String> Factory::InternalizeStringWithKey< ...@@ -212,9 +212,7 @@ template Handle<String> Factory::InternalizeStringWithKey<
MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string, MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
PretenureFlag pretenure) { PretenureFlag pretenure) {
int length = string.length(); int length = string.length();
if (length == 1) { if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
return LookupSingleCharacterStringFromCode(string[0]);
}
Handle<SeqOneByteString> result; Handle<SeqOneByteString> result;
ASSIGN_RETURN_ON_EXCEPTION( ASSIGN_RETURN_ON_EXCEPTION(
isolate(), isolate(),
...@@ -241,22 +239,55 @@ MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string, ...@@ -241,22 +239,55 @@ MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
// since UTF8 is backwards compatible with ASCII. // since UTF8 is backwards compatible with ASCII.
return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure); return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure);
} }
// Non-ASCII and we need to decode. // Non-ASCII and we need to decode.
CALL_HEAP_FUNCTION( Access<UnicodeCache::Utf8Decoder>
isolate(), decoder(isolate()->unicode_cache()->utf8_decoder());
isolate()->heap()->AllocateStringFromUtf8Slow(string, decoder->Reset(string.start() + non_ascii_start,
non_ascii_start, length - non_ascii_start);
pretenure), 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); 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, MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
PretenureFlag pretenure) { PretenureFlag pretenure) {
CALL_HEAP_FUNCTION( int length = string.length();
isolate(), const uc16* start = string.start();
isolate()->heap()->AllocateStringFromTwoByte(string, pretenure), if (String::IsOneByte(start, length)) {
String); 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;
}
} }
...@@ -328,6 +359,9 @@ MaybeHandle<Map> Factory::InternalizedStringMapForString( ...@@ -328,6 +359,9 @@ MaybeHandle<Map> Factory::InternalizedStringMapForString(
MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString( MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
int length, PretenureFlag pretenure) { int length, PretenureFlag pretenure) {
if (length > String::kMaxLength || length < 0) {
return isolate()->Throw<SeqOneByteString>(NewInvalidStringLengthError());
}
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
isolate(), isolate(),
isolate()->heap()->AllocateRawOneByteString(length, pretenure), isolate()->heap()->AllocateRawOneByteString(length, pretenure),
...@@ -337,6 +371,9 @@ MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString( ...@@ -337,6 +371,9 @@ MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
MaybeHandle<SeqTwoByteString> Factory::NewRawTwoByteString( MaybeHandle<SeqTwoByteString> Factory::NewRawTwoByteString(
int length, PretenureFlag pretenure) { int length, PretenureFlag pretenure) {
if (length > String::kMaxLength || length < 0) {
return isolate()->Throw<SeqTwoByteString>(NewInvalidStringLengthError());
}
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
isolate(), isolate(),
isolate()->heap()->AllocateRawTwoByteString(length, pretenure), isolate()->heap()->AllocateRawTwoByteString(length, pretenure),
...@@ -586,8 +623,7 @@ MaybeHandle<String> Factory::NewExternalStringFromAscii( ...@@ -586,8 +623,7 @@ MaybeHandle<String> Factory::NewExternalStringFromAscii(
const ExternalAsciiString::Resource* resource) { const ExternalAsciiString::Resource* resource) {
size_t length = resource->length(); size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) { if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->ThrowInvalidStringLength(); return isolate()->Throw<String>(NewInvalidStringLengthError());
return MaybeHandle<String>();
} }
Handle<Map> map = external_ascii_string_map(); Handle<Map> map = external_ascii_string_map();
...@@ -605,8 +641,7 @@ MaybeHandle<String> Factory::NewExternalStringFromTwoByte( ...@@ -605,8 +641,7 @@ MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
const ExternalTwoByteString::Resource* resource) { const ExternalTwoByteString::Resource* resource) {
size_t length = resource->length(); size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) { if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->ThrowInvalidStringLength(); return isolate()->Throw<String>(NewInvalidStringLengthError());
return MaybeHandle<String>();
} }
// For small strings we check whether the resource contains only // For small strings we check whether the resource contains only
......
...@@ -122,6 +122,23 @@ class Factory V8_FINAL { ...@@ -122,6 +122,23 @@ class Factory V8_FINAL {
OneByteVector(str), pretenure).ToHandleChecked(); 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. // TODO(dcarney): remove this function.
MUST_USE_RESULT inline MaybeHandle<String> NewStringFromAscii( MUST_USE_RESULT inline MaybeHandle<String> NewStringFromAscii(
Vector<const char> str, Vector<const char> str,
......
...@@ -98,9 +98,7 @@ AllocationResult Heap::AllocateInternalizedStringImpl( ...@@ -98,9 +98,7 @@ AllocationResult Heap::AllocateInternalizedStringImpl(
AllocationResult Heap::AllocateOneByteInternalizedString( AllocationResult Heap::AllocateOneByteInternalizedString(
Vector<const uint8_t> str, Vector<const uint8_t> str,
uint32_t hash_field) { uint32_t hash_field) {
if (str.length() > String::kMaxLength) { CHECK_GE(String::kMaxLength, str.length());
return isolate()->ThrowInvalidStringLength();
}
// Compute map and object size. // Compute map and object size.
Map* map = ascii_internalized_string_map(); Map* map = ascii_internalized_string_map();
int size = SeqOneByteString::SizeFor(str.length()); int size = SeqOneByteString::SizeFor(str.length());
...@@ -131,9 +129,7 @@ AllocationResult Heap::AllocateOneByteInternalizedString( ...@@ -131,9 +129,7 @@ AllocationResult Heap::AllocateOneByteInternalizedString(
AllocationResult Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str, AllocationResult Heap::AllocateTwoByteInternalizedString(Vector<const uc16> str,
uint32_t hash_field) { uint32_t hash_field) {
if (str.length() > String::kMaxLength) { CHECK_GE(String::kMaxLength, str.length());
return isolate()->ThrowInvalidStringLength();
}
// Compute map and object size. // Compute map and object size.
Map* map = internalized_string_map(); Map* map = internalized_string_map();
int size = SeqTwoByteString::SizeFor(str.length()); int size = SeqTwoByteString::SizeFor(str.length());
...@@ -540,10 +536,9 @@ Isolate* Heap::isolate() { ...@@ -540,10 +536,9 @@ Isolate* Heap::isolate() {
// Warning: Do not use the identifiers __object__, __maybe_object__ or // Warning: Do not use the identifiers __object__, __maybe_object__ or
// __scope__ in a call to this macro. // __scope__ in a call to this macro.
#define RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ #define RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \
if (!__allocation__.IsRetry()) { \ if (__allocation__.To(&__object__)) { \
__object__ = __allocation__.ToObjectChecked(); \ ASSERT(__object__ != (ISOLATE)->heap()->exception()); \
if (__object__ == (ISOLATE)->heap()->exception()) { RETURN_EMPTY; } \
RETURN_VALUE; \ RETURN_VALUE; \
} }
...@@ -551,18 +546,18 @@ Isolate* Heap::isolate() { ...@@ -551,18 +546,18 @@ Isolate* Heap::isolate() {
do { \ do { \
AllocationResult __allocation__ = FUNCTION_CALL; \ AllocationResult __allocation__ = FUNCTION_CALL; \
Object* __object__ = NULL; \ Object* __object__ = NULL; \
RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \
(ISOLATE)->heap()->CollectGarbage(__allocation__.RetrySpace(), \ (ISOLATE)->heap()->CollectGarbage(__allocation__.RetrySpace(), \
"allocation failure"); \ "allocation failure"); \
__allocation__ = FUNCTION_CALL; \ __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)->counters()->gc_last_resort_from_handles()->Increment(); \
(ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \ (ISOLATE)->heap()->CollectAllAvailableGarbage("last resort gc"); \
{ \ { \
AlwaysAllocateScope __scope__(ISOLATE); \ AlwaysAllocateScope __scope__(ISOLATE); \
__allocation__ = FUNCTION_CALL; \ __allocation__ = FUNCTION_CALL; \
} \ } \
RETURN_OBJECT_UNLESS_EXCEPTION(ISOLATE, RETURN_VALUE, RETURN_EMPTY) \ RETURN_OBJECT_UNLESS_RETRY(ISOLATE, RETURN_VALUE) \
/* TODO(1181417): Fix this. */ \ /* TODO(1181417): Fix this. */ \
v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \ v8::internal::Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); \
RETURN_EMPTY; \ RETURN_EMPTY; \
......
...@@ -3750,64 +3750,6 @@ AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) { ...@@ -3750,64 +3750,6 @@ AllocationResult Heap::CopyJSObject(JSObject* source, AllocationSite* site) {
} }
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, static inline void WriteOneByteData(Vector<const char> vector,
uint8_t* chars, uint8_t* chars,
int len) { int len) {
...@@ -3864,9 +3806,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl( ...@@ -3864,9 +3806,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl(
int size; int size;
Map* map; Map* map;
if (chars < 0 || chars > String::kMaxLength) { ASSERT_LE(0, chars);
return isolate()->ThrowInvalidStringLength(); ASSERT_GE(String::kMaxLength, chars);
}
if (is_one_byte) { if (is_one_byte) {
map = ascii_internalized_string_map(); map = ascii_internalized_string_map();
size = SeqOneByteString::SizeFor(chars); size = SeqOneByteString::SizeFor(chars);
...@@ -3913,9 +3854,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl<false>( ...@@ -3913,9 +3854,8 @@ AllocationResult Heap::AllocateInternalizedStringImpl<false>(
AllocationResult Heap::AllocateRawOneByteString(int length, AllocationResult Heap::AllocateRawOneByteString(int length,
PretenureFlag pretenure) { PretenureFlag pretenure) {
if (length < 0 || length > String::kMaxLength) { ASSERT_LE(0, length);
return isolate()->ThrowInvalidStringLength(); ASSERT_GE(String::kMaxLength, length);
}
int size = SeqOneByteString::SizeFor(length); int size = SeqOneByteString::SizeFor(length);
ASSERT(size <= SeqOneByteString::kMaxSize); ASSERT(size <= SeqOneByteString::kMaxSize);
AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure); AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
...@@ -3937,9 +3877,8 @@ AllocationResult Heap::AllocateRawOneByteString(int length, ...@@ -3937,9 +3877,8 @@ AllocationResult Heap::AllocateRawOneByteString(int length,
AllocationResult Heap::AllocateRawTwoByteString(int length, AllocationResult Heap::AllocateRawTwoByteString(int length,
PretenureFlag pretenure) { PretenureFlag pretenure) {
if (length < 0 || length > String::kMaxLength) { ASSERT_LE(0, length);
return isolate()->ThrowInvalidStringLength(); ASSERT_GE(String::kMaxLength, length);
}
int size = SeqTwoByteString::SizeFor(length); int size = SeqTwoByteString::SizeFor(length);
ASSERT(size <= SeqTwoByteString::kMaxSize); ASSERT(size <= SeqTwoByteString::kMaxSize);
AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure); AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
......
...@@ -1792,29 +1792,6 @@ class Heap { ...@@ -1792,29 +1792,6 @@ class Heap {
MUST_USE_RESULT AllocationResult AllocateRawTwoByteString( MUST_USE_RESULT AllocationResult AllocateRawTwoByteString(
int length, PretenureFlag pretenure); 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(); bool CreateInitialMaps();
void CreateInitialObjects(); void CreateInitialObjects();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment