Revision: 17497
Author:   [email protected]
Date:     Tue Nov  5 15:36:15 2013 UTC
Log:      Revert "Handlify concat string and substring."

This reverts r17490.

[email protected]
BUG=

Review URL: https://codereview.chromium.org/59973004
http://code.google.com/p/v8/source/detail?r=17497

Modified:
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/handles.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/test/mjsunit/string-slices.js

=======================================
--- /branches/bleeding_edge/src/factory.cc      Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/factory.cc      Tue Nov  5 15:36:15 2013 UTC
@@ -287,43 +287,11 @@
 }


-// Returns true for a character in a range.  Both limits are inclusive.
-static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
-  // This makes uses of the the unsigned wraparound.
-  return character - from <= to - from;
-}
-
-
-static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
-                                                          uint16_t c1,
-                                                          uint16_t c2) {
-  // Numeric strings have a different hash algorithm not known by
-  // LookupTwoCharsStringIfExists, so we skip this step for such strings.
-  if (!Between(c1, '0', '9') || !Between(c2, '0', '9')) {
-    String* result;
-    StringTable* table = isolate->heap()->string_table();
-    if (table->LookupTwoCharsStringIfExists(c1, c2, &result)) {
-      return handle(result);
-    }
-  }
-
-  // Now we know the length is 2, we might as well make use of that fact
-  // when building the new string.
-  if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
-    // We can do this.
- ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. - Handle<SeqOneByteString> str = isolate->factory()->NewRawOneByteString(2);
-    uint8_t* dest = str->GetChars();
-    dest[0] = static_cast<uint8_t>(c1);
-    dest[1] = static_cast<uint8_t>(c2);
-    return str;
-  } else {
- Handle<SeqTwoByteString> str = isolate->factory()->NewRawTwoByteString(2);
-    uc16* dest = str->GetChars();
-    dest[0] = c1;
-    dest[1] = c2;
-    return str;
-  }
+Handle<String> Factory::NewConsString(Handle<String> first,
+                                      Handle<String> second) {
+  CALL_HEAP_FUNCTION(isolate(),
+ isolate()->heap()->AllocateConsString(*first, *second),
+                     String);
 }


@@ -337,99 +305,6 @@
String::WriteToFlat(*second, sink + first->length(), 0, second->length());
   return result;
 }
-
-
-Handle<ConsString> Factory::NewRawConsString(String::Encoding encoding) {
-  Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
-      ? cons_ascii_string_map() : cons_string_map();
-  CALL_HEAP_FUNCTION(isolate(),
-                     isolate()->heap()->Allocate(*map, NEW_SPACE),
-                     ConsString);
-}
-
-
-Handle<String> Factory::NewConsString(Handle<String> left,
-                                      Handle<String> right) {
-  int left_length = left->length();
-  if (left_length == 0) return right;
-  int right_length = right->length();
-  if (right_length == 0) return left;
-
-  int length = left_length + right_length;
-
-  if (length == 2) {
-    uint16_t c1 = left->Get(0);
-    uint16_t c2 = right->Get(0);
-    return MakeOrFindTwoCharacterString(isolate(), c1, c2);
-  }
-
-  // Make sure that an out of memory exception is thrown if the length
-  // of the new cons string is too large.
-  if (length > String::kMaxLength || length < 0) {
-    isolate()->context()->mark_out_of_memory();
-    V8::FatalProcessOutOfMemory("String concatenation result too large.");
-    UNREACHABLE();
-    return Handle<String>::null();
-  }
-
-  bool left_is_one_byte = left->IsOneByteRepresentation();
-  bool right_is_one_byte = right->IsOneByteRepresentation();
-  bool is_one_byte = left_is_one_byte && right_is_one_byte;
-  bool is_one_byte_data_in_two_byte_string = false;
-  if (!is_one_byte) {
-    // At least one of the strings uses two-byte representation so we
-    // can't use the fast case code for short ASCII strings below, but
-    // we can try to save memory if all chars actually fit in ASCII.
-    is_one_byte_data_in_two_byte_string =
-        left->HasOnlyOneByteChars() && right->HasOnlyOneByteChars();
-    if (is_one_byte_data_in_two_byte_string) {
- isolate()->counters()->string_add_runtime_ext_to_ascii()->Increment();
-    }
-  }
-
-  // If the resulting string is small make a flat string.
-  if (length < ConsString::kMinLength) {
-    // Note that neither of the two inputs can be a slice because:
-    STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
-    ASSERT(left->IsFlat());
-    ASSERT(right->IsFlat());
-
-    if (is_one_byte) {
-      Handle<SeqOneByteString> result = NewRawOneByteString(length);
-      DisallowHeapAllocation no_gc;
-      uint8_t* dest = result->GetChars();
-      // Copy left part.
-      const uint8_t* src = left->IsExternalString()
-          ? Handle<ExternalAsciiString>::cast(left)->GetChars()
-          : Handle<SeqOneByteString>::cast(left)->GetChars();
-      for (int i = 0; i < left_length; i++) *dest++ = src[i];
-      // Copy right part.
-      src = right->IsExternalString()
-          ? Handle<ExternalAsciiString>::cast(right)->GetChars()
-          : Handle<SeqOneByteString>::cast(right)->GetChars();
-      for (int i = 0; i < right_length; i++) *dest++ = src[i];
-      return result;
-    }
-
-    return (is_one_byte_data_in_two_byte_string)
- ? ConcatStringContent<uint8_t>(NewRawOneByteString(length), left, right) - : ConcatStringContent<uc16>(NewRawTwoByteString(length), left, right);
-  }
-
-  Handle<ConsString> result = NewRawConsString(
-      (is_one_byte || is_one_byte_data_in_two_byte_string)
-          ? String::ONE_BYTE_ENCODING
-          : String::TWO_BYTE_ENCODING);
-
-  DisallowHeapAllocation no_gc;
-  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
-
-  result->set_hash_field(String::kEmptyHashField);
-  result->set_length(length);
-  result->set_first(*left, mode);
-  result->set_second(*right, mode);
-  return result;
-}


 Handle<String> Factory::NewFlatConcatString(Handle<String> first,
@@ -446,89 +321,22 @@
 }


-Handle<SlicedString> Factory::NewRawSlicedString(String::Encoding encoding) {
-  Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
-      ? sliced_ascii_string_map() : sliced_string_map();
+Handle<String> Factory::NewSubString(Handle<String> str,
+                                     int begin,
+                                     int end) {
   CALL_HEAP_FUNCTION(isolate(),
-                     isolate()->heap()->Allocate(*map, NEW_SPACE),
-                     SlicedString);
+                     str->SubString(begin, end),
+                     String);
 }


 Handle<String> Factory::NewProperSubString(Handle<String> str,
                                            int begin,
                                            int end) {
-#if VERIFY_HEAP
-  if (FLAG_verify_heap) str->StringVerify();
-#endif
   ASSERT(begin > 0 || end < str->length());
-
-  int length = end - begin;
-  if (length <= 0) return empty_string();
-  if (length == 1) {
-    return LookupSingleCharacterStringFromCode(isolate(), str->Get(begin));
-  }
-  if (length == 2) {
- // Optimization for 2-byte strings often used as keys in a decompression
-    // dictionary.  Check whether we already have the string in the string
-    // table to prevent creation of many unnecessary strings.
-    uint16_t c1 = str->Get(begin);
-    uint16_t c2 = str->Get(begin + 1);
-    return MakeOrFindTwoCharacterString(isolate(), c1, c2);
-  }
-
-  if (!FLAG_string_slices || length < SlicedString::kMinLength) {
-    if (str->IsOneByteRepresentation()) {
-      Handle<SeqOneByteString> result = NewRawOneByteString(length);
-      uint8_t* dest = result->GetChars();
-      DisallowHeapAllocation no_gc;
-      String::WriteToFlat(*str, dest, begin, end);
-      return result;
-    } else {
-      Handle<SeqTwoByteString> result = NewRawTwoByteString(length);
-      uc16* dest = result->GetChars();
-      DisallowHeapAllocation no_gc;
-      String::WriteToFlat(*str, dest, begin, end);
-      return result;
-    }
-  }
-
-  int offset = begin;
-
-  while (str->IsConsString()) {
-    Handle<ConsString> cons = Handle<ConsString>::cast(str);
-    int split = cons->first()->length();
-    if (split <= offset) {
-      // Slice is fully contained in the second part.
-      str = Handle<String>(cons->second(), isolate());
-      offset -= split;  // Adjust for offset.
-      continue;
-    } else if (offset + length <= split) {
-      // Slice is fully contained in the first part.
-      str = Handle<String>(cons->first(), isolate());
-      continue;
-    }
-    break;
-  }
-
-  if (str->IsSlicedString()) {
-    Handle<SlicedString> slice = Handle<SlicedString>::cast(str);
-    str = Handle<String>(slice->parent(), isolate());
-    offset += slice->offset();
-  } else {
-    str = FlattenGetString(str);
-  }
-
-  ASSERT(str->IsSeqString() || str->IsExternalString());
-  Handle<SlicedString> slice = NewRawSlicedString(
-      str->IsOneByteRepresentation() ? String::ONE_BYTE_ENCODING
-                                     : String::TWO_BYTE_ENCODING);
-
-  slice->set_hash_field(String::kEmptyHashField);
-  slice->set_length(length);
-  slice->set_parent(*str);
-  slice->set_offset(offset);
-  return slice;
+  CALL_HEAP_FUNCTION(isolate(),
+ isolate()->heap()->AllocateSubString(*str, begin, end),
+                     String);
 }


=======================================
--- /branches/bleeding_edge/src/factory.h       Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/factory.h       Tue Nov  5 15:36:15 2013 UTC
@@ -158,28 +158,23 @@
       PretenureFlag pretenure = NOT_TENURED);

   // Create a new cons string object which consists of a pair of strings.
-  Handle<String> NewConsString(Handle<String> left,
-                               Handle<String> right);
-
-  Handle<ConsString> NewRawConsString(String::Encoding encoding);
+  Handle<String> NewConsString(Handle<String> first,
+                               Handle<String> second);

// Create a new sequential string containing the concatenation of the inputs.
   Handle<String> NewFlatConcatString(Handle<String> first,
                                      Handle<String> second);

+  // Create a new string object which holds a substring of a string.
+  Handle<String> NewSubString(Handle<String> str,
+                              int begin,
+                              int end);
+
   // Create a new string object which holds a proper substring of a string.
   Handle<String> NewProperSubString(Handle<String> str,
                                     int begin,
                                     int end);

-  // Create a new string object which holds a substring of a string.
-  Handle<String> NewSubString(Handle<String> str, int begin, int end) {
-    if (begin == 0 && end == str->length()) return str;
-    return NewProperSubString(str, begin, end);
-  }
-
-  Handle<SlicedString> NewRawSlicedString(String::Encoding encoding);
-
   // Creates a new external String object.  There are two String encodings
   // in the system: ASCII and two byte.  Unlike other String types, it does
   // not make sense to have a UTF-8 factory function for external strings,
=======================================
--- /branches/bleeding_edge/src/handles.cc      Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/handles.cc      Tue Nov  5 15:36:15 2013 UTC
@@ -229,12 +229,11 @@
 }


-Handle<String> LookupSingleCharacterStringFromCode(Isolate* isolate,
+Handle<Object> LookupSingleCharacterStringFromCode(Isolate* isolate,
                                                    uint32_t index) {
   CALL_HEAP_FUNCTION(
       isolate,
-      isolate->heap()->LookupSingleCharacterStringFromCode(index),
-      String);
+      isolate->heap()->LookupSingleCharacterStringFromCode(index), Object);
 }


=======================================
--- /branches/bleeding_edge/src/handles.h       Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/handles.h       Tue Nov  5 15:36:15 2013 UTC
@@ -252,7 +252,7 @@
                            Handle<Object> obj,
                            Handle<Object> key);

-Handle<String> LookupSingleCharacterStringFromCode(Isolate* isolate,
+Handle<Object> LookupSingleCharacterStringFromCode(Isolate* isolate,
                                                    uint32_t index);

 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray>,
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/heap.cc Tue Nov  5 15:36:15 2013 UTC
@@ -3772,6 +3772,262 @@
   message->set_stack_frames(stack_frames);
   return result;
 }
+
+
+
+// Returns true for a character in a range.  Both limits are inclusive.
+static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
+  // This makes uses of the the unsigned wraparound.
+  return character - from <= to - from;
+}
+
+
+MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
+    Heap* heap,
+    uint16_t c1,
+    uint16_t c2) {
+  String* result;
+  // Numeric strings have a different hash algorithm not known by
+  // LookupTwoCharsStringIfExists, so we skip this step for such strings.
+  if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
+ heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) {
+    return result;
+  // Now we know the length is 2, we might as well make use of that fact
+  // when building the new string.
+ } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
+    // We can do this.
+ ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
+    Object* result;
+    { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
+      if (!maybe_result->ToObject(&result)) return maybe_result;
+    }
+    uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
+    dest[0] = static_cast<uint8_t>(c1);
+    dest[1] = static_cast<uint8_t>(c2);
+    return result;
+  } else {
+    Object* result;
+    { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
+      if (!maybe_result->ToObject(&result)) return maybe_result;
+    }
+    uc16* dest = SeqTwoByteString::cast(result)->GetChars();
+    dest[0] = c1;
+    dest[1] = c2;
+    return result;
+  }
+}
+
+
+MaybeObject* Heap::AllocateConsString(String* first, String* second) {
+  int first_length = first->length();
+  if (first_length == 0) {
+    return second;
+  }
+
+  int second_length = second->length();
+  if (second_length == 0) {
+    return first;
+  }
+
+  int length = first_length + second_length;
+
+  // Optimization for 2-byte strings often used as keys in a decompression
+  // dictionary.  Check whether we already have the string in the string
+  // table to prevent creation of many unneccesary strings.
+  if (length == 2) {
+    uint16_t c1 = first->Get(0);
+    uint16_t c2 = second->Get(0);
+    return MakeOrFindTwoCharacterString(this, c1, c2);
+  }
+
+  bool first_is_one_byte = first->IsOneByteRepresentation();
+  bool second_is_one_byte = second->IsOneByteRepresentation();
+  bool is_one_byte = first_is_one_byte && second_is_one_byte;
+  // Make sure that an out of memory exception is thrown if the length
+  // of the new cons string is too large.
+  if (length > String::kMaxLength || length < 0) {
+    isolate()->context()->mark_out_of_memory();
+    return Failure::OutOfMemoryException(0x4);
+  }
+
+  bool is_one_byte_data_in_two_byte_string = false;
+  if (!is_one_byte) {
+    // At least one of the strings uses two-byte representation so we
+    // can't use the fast case code for short ASCII strings below, but
+    // we can try to save memory if all chars actually fit in ASCII.
+    is_one_byte_data_in_two_byte_string =
+        first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars();
+    if (is_one_byte_data_in_two_byte_string) {
+      isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
+    }
+  }
+
+  // If the resulting string is small make a flat string.
+  if (length < ConsString::kMinLength) {
+    // Note that neither of the two inputs can be a slice because:
+    STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
+    ASSERT(first->IsFlat());
+    ASSERT(second->IsFlat());
+    if (is_one_byte) {
+      Object* result;
+      { MaybeObject* maybe_result = AllocateRawOneByteString(length);
+        if (!maybe_result->ToObject(&result)) return maybe_result;
+      }
+      // Copy the characters into the new object.
+      uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
+      // Copy first part.
+      const uint8_t* src;
+      if (first->IsExternalString()) {
+        src = ExternalAsciiString::cast(first)->GetChars();
+      } else {
+        src = SeqOneByteString::cast(first)->GetChars();
+      }
+      for (int i = 0; i < first_length; i++) *dest++ = src[i];
+      // Copy second part.
+      if (second->IsExternalString()) {
+        src = ExternalAsciiString::cast(second)->GetChars();
+      } else {
+        src = SeqOneByteString::cast(second)->GetChars();
+      }
+      for (int i = 0; i < second_length; i++) *dest++ = src[i];
+      return result;
+    } else {
+      if (is_one_byte_data_in_two_byte_string) {
+        Object* result;
+        { MaybeObject* maybe_result = AllocateRawOneByteString(length);
+          if (!maybe_result->ToObject(&result)) return maybe_result;
+        }
+        // Copy the characters into the new object.
+        uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
+        String::WriteToFlat(first, dest, 0, first_length);
+        String::WriteToFlat(second, dest + first_length, 0, second_length);
+ isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
+        return result;
+      }
+
+      Object* result;
+      { MaybeObject* maybe_result = AllocateRawTwoByteString(length);
+        if (!maybe_result->ToObject(&result)) return maybe_result;
+      }
+      // Copy the characters into the new object.
+      uc16* dest = SeqTwoByteString::cast(result)->GetChars();
+      String::WriteToFlat(first, dest, 0, first_length);
+      String::WriteToFlat(second, dest + first_length, 0, second_length);
+      return result;
+    }
+  }
+
+  Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ?
+      cons_ascii_string_map() : cons_string_map();
+
+  Object* result;
+  { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+
+  DisallowHeapAllocation no_gc;
+  ConsString* cons_string = ConsString::cast(result);
+  WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
+  cons_string->set_length(length);
+  cons_string->set_hash_field(String::kEmptyHashField);
+  cons_string->set_first(first, mode);
+  cons_string->set_second(second, mode);
+  return result;
+}
+
+
+MaybeObject* Heap::AllocateSubString(String* buffer,
+                                     int start,
+                                     int end,
+                                     PretenureFlag pretenure) {
+  int length = end - start;
+  if (length <= 0) {
+    return empty_string();
+  } else if (length == 1) {
+    return LookupSingleCharacterStringFromCode(buffer->Get(start));
+  } else if (length == 2) {
+ // Optimization for 2-byte strings often used as keys in a decompression
+    // dictionary.  Check whether we already have the string in the string
+    // table to prevent creation of many unnecessary strings.
+    uint16_t c1 = buffer->Get(start);
+    uint16_t c2 = buffer->Get(start + 1);
+    return MakeOrFindTwoCharacterString(this, c1, c2);
+  }
+
+  // Make an attempt to flatten the buffer to reduce access time.
+  buffer = buffer->TryFlattenGetString();
+
+  if (!FLAG_string_slices ||
+      !buffer->IsFlat() ||
+      length < SlicedString::kMinLength ||
+      pretenure == TENURED) {
+    Object* result;
+    // WriteToFlat takes care of the case when an indirect string has a
+    // different encoding from its underlying string.  These encodings may
+    // differ because of externalization.
+    bool is_one_byte = buffer->IsOneByteRepresentation();
+    { MaybeObject* maybe_result = is_one_byte
+ ? AllocateRawOneByteString(length, pretenure) + : AllocateRawTwoByteString(length, pretenure);
+      if (!maybe_result->ToObject(&result)) return maybe_result;
+    }
+    String* string_result = String::cast(result);
+    // Copy the characters into the new object.
+    if (is_one_byte) {
+      ASSERT(string_result->IsOneByteRepresentation());
+      uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars();
+      String::WriteToFlat(buffer, dest, start, end);
+    } else {
+      ASSERT(string_result->IsTwoByteRepresentation());
+      uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
+      String::WriteToFlat(buffer, dest, start, end);
+    }
+    return result;
+  }
+
+  ASSERT(buffer->IsFlat());
+#if VERIFY_HEAP
+  if (FLAG_verify_heap) {
+    buffer->StringVerify();
+  }
+#endif
+
+  Object* result;
+ // When slicing an indirect string we use its encoding for a newly created + // slice and don't check the encoding of the underlying string. This is safe
+  // even if the encodings are different because of externalization.  If an
+ // indirect ASCII string is pointing to a two-byte string, the two-byte char
+  // codes of the underlying string must still fit into ASCII (because
+  // externalization must not change char codes).
+  { Map* map = buffer->IsOneByteRepresentation()
+                 ? sliced_ascii_string_map()
+                 : sliced_string_map();
+    MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+
+  DisallowHeapAllocation no_gc;
+  SlicedString* sliced_string = SlicedString::cast(result);
+  sliced_string->set_length(length);
+  sliced_string->set_hash_field(String::kEmptyHashField);
+  if (buffer->IsConsString()) {
+    ConsString* cons = ConsString::cast(buffer);
+    ASSERT(cons->second()->length() == 0);
+    sliced_string->set_parent(cons->first());
+    sliced_string->set_offset(start);
+  } else if (buffer->IsSlicedString()) {
+    // Prevent nesting sliced strings.
+    SlicedString* parent_slice = SlicedString::cast(buffer);
+    sliced_string->set_parent(parent_slice->parent());
+    sliced_string->set_offset(start + parent_slice->offset());
+  } else {
+    sliced_string->set_parent(buffer);
+    sliced_string->set_offset(start);
+  }
+  ASSERT(sliced_string->parent()->IsSeqString() ||
+         sliced_string->parent()->IsExternalString());
+  return result;
+}


 MaybeObject* Heap::AllocateExternalStringFromAscii(
=======================================
--- /branches/bleeding_edge/src/heap.h  Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/heap.h  Tue Nov  5 15:36:15 2013 UTC
@@ -1068,6 +1068,25 @@
       Object* stack_trace,
       Object* stack_frames);

+  // Allocates a new cons string object.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  MUST_USE_RESULT MaybeObject* AllocateConsString(String* first,
+                                                  String* second);
+
+ // Allocates a new sub string object which is a substring of an underlying
+  // string buffer stretching from the index start (inclusive) to the index
+  // end (exclusive).
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  MUST_USE_RESULT MaybeObject* AllocateSubString(
+      String* buffer,
+      int start,
+      int end,
+      PretenureFlag pretenure = NOT_TENURED);
+
   // Allocate a new external string object, which is backed by a string
   // resource that resides outside the V8 heap.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue Nov  5 15:33:14 2013 UTC
+++ /branches/bleeding_edge/src/objects.cc      Tue Nov  5 15:36:15 2013 UTC
@@ -9278,6 +9278,14 @@
   hasher.length_ = utf16_length;
   return hasher.GetHashField();
 }
+
+
+MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
+  Heap* heap = GetHeap();
+  if (start == 0 && end == length()) return this;
+ MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
+  return result;
+}


 void String::PrintOn(FILE* file) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Nov  5 15:33:14 2013 UTC
+++ /branches/bleeding_edge/src/objects.h       Tue Nov  5 15:36:15 2013 UTC
@@ -8513,6 +8513,11 @@
   // ASCII and two byte string types.
   bool MarkAsUndetectable();

+  // Return a substring.
+  MUST_USE_RESULT MaybeObject* SubString(int from,
+                                         int to,
+ PretenureFlag pretenure = NOT_TENURED);
+
   // String equality operations.
   inline bool Equals(String* other);
bool IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false);
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Nov  5 14:07:07 2013 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Tue Nov  5 15:36:15 2013 UTC
@@ -4387,10 +4387,10 @@


 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
-  HandleScope scope(isolate);
+  SealHandleScope shs(isolate);
   ASSERT(args.length() == 3);

-  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
+  CONVERT_ARG_CHECKED(String, value, 0);
   int start, end;
// We have a fast integer-only case here to avoid a conversion to double in
   // the common case where from and to are Smis.
@@ -4407,10 +4407,13 @@
   }
   RUNTIME_ASSERT(end >= start);
   RUNTIME_ASSERT(start >= 0);
-  RUNTIME_ASSERT(end <= string->length());
+  RUNTIME_ASSERT(end <= value->length());
   isolate->counters()->sub_string_runtime()->Increment();
-
-  return *isolate->factory()->NewSubString(string, start, end);
+  if (end - start == 1) {
+     return isolate->heap()->LookupSingleCharacterStringFromCode(
+         value->Get(start));
+  }
+  return value->SubString(start, end);
 }


@@ -6497,31 +6500,30 @@


 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
-  HandleScope scope(isolate);
+  SealHandleScope shs(isolate);
   ASSERT(args.length() == 3);

-  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
+  CONVERT_ARG_CHECKED(String, s, 0);
   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);

-  string = FlattenGetString(string);
-  int length = string->length();
+  s->TryFlatten();
+  int length = s->length();

   int left = 0;
   if (trimLeft) {
-    while (left < length && IsTrimWhiteSpace(string->Get(left))) {
+    while (left < length && IsTrimWhiteSpace(s->Get(left))) {
       left++;
     }
   }

   int right = length;
   if (trimRight) {
-    while (right > left && IsTrimWhiteSpace(string->Get(right - 1))) {
+    while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
       right--;
     }
   }
-
-  return *isolate->factory()->NewSubString(string, left, right);
+  return s->SubString(left, right);
 }


@@ -6924,12 +6926,12 @@


 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
-  HandleScope scope(isolate);
+  SealHandleScope shs(isolate);
   ASSERT(args.length() == 2);
-  CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
+  CONVERT_ARG_CHECKED(String, str1, 0);
+  CONVERT_ARG_CHECKED(String, str2, 1);
   isolate->counters()->string_add_runtime()->Increment();
-  return *isolate->factory()->NewConsString(str1, str2);
+  return isolate->heap()->AllocateConsString(str1, str2);
 }


=======================================
--- /branches/bleeding_edge/test/mjsunit/string-slices.js Tue Nov 5 14:07:07 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/string-slices.js Tue Nov 5 15:36:15 2013 UTC
@@ -223,14 +223,3 @@
 test_crankshaft();
 %OptimizeFunctionOnNextCall(test_crankshaft);
 test_crankshaft();
-
-var s1 = "12345678901234567890";
-var s2 = "abcdefghijklmnopqrstuvwxyz";
-var c1 = s1 + s2;
-var c2 = s1 + c1 + s2;
-assertEquals("234567890123456789", c1.substring(1, 19));
-assertEquals("bcdefghijklmno", c1.substring(21, 35));
-assertEquals("2345678901234567890abcdefghijklmno", c1.substring(1, 35));
-assertEquals("234567890123456789", c2.substring(1, 19));
-assertEquals("bcdefghijklmno", c2.substring(41, 55));
-assertEquals("2345678901234567890abcdefghijklmno", c2.substring(21, 55));

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to