Move invalid string length check to the factory.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 18 Jun 2014 13:26:02 +0000 (13:26 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 18 Jun 2014 13:26:02 +0000 (13:26 +0000)
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

src/factory.cc
src/factory.h
src/heap-inl.h
src/heap.cc
src/heap.h

index 86c314c..3d373fb 100644 (file)
@@ -212,9 +212,7 @@ template Handle<String> Factory::InternalizeStringWithKey<
 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(),
@@ -241,22 +239,55 @@ MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
     // 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;
+  }
 }
 
 
@@ -328,6 +359,9 @@ MaybeHandle<Map> Factory::InternalizedStringMapForString(
 
 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),
@@ -337,6 +371,9 @@ MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
 
 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),
@@ -586,8 +623,7 @@ MaybeHandle<String> Factory::NewExternalStringFromAscii(
     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();
@@ -605,8 +641,7 @@ MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
     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
index 7ef8911..e22ea8d 100644 (file)
@@ -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<String> NewStringFromAscii(
       Vector<const char> str,
index 64125bc..2e80452 100644 (file)
@@ -98,9 +98,7 @@ AllocationResult Heap::AllocateInternalizedStringImpl(
 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());
@@ -131,9 +129,7 @@ AllocationResult Heap::AllocateOneByteInternalizedString(
 
 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());
@@ -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;                                                              \
index 7806f0a..7260e7a 100644 (file)
@@ -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,
                                     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<false>(
 
 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);
index 2671a52..97de93e 100644 (file)
@@ -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<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();