Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index 8dbda270fe3644d6647db538d05b67274e19aacf..6d66dda02df7f558c08ebe76e08dd30d988accdb 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -1288,6 +1288,10 @@ class ScavengingVisitor : public StaticVisitorBase { |
&ObjectEvacuationStrategy<POINTER_OBJECT>:: |
template VisitSpecialized<ConsString::kSize>); |
+ table_.Register(kVisitSlicedString, |
+ &ObjectEvacuationStrategy<POINTER_OBJECT>:: |
+ template VisitSpecialized<SlicedString::kSize>); |
+ |
table_.Register(kVisitSharedFunctionInfo, |
&ObjectEvacuationStrategy<POINTER_OBJECT>:: |
template VisitSpecialized<SharedFunctionInfo::kSize>); |
@@ -2545,6 +2549,8 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) { |
// If the resulting string is small make a flat string. |
if (length < String::kMinNonFlatLength) { |
+ // Note that neither of the two inputs can be a slice because: |
+ STATIC_ASSERT(String::kMinNonFlatLength <= SlicedString::kMinLength); |
ASSERT(first->IsFlat()); |
ASSERT(second->IsFlat()); |
if (is_ascii) { |
@@ -2636,24 +2642,69 @@ MaybeObject* Heap::AllocateSubString(String* buffer, |
// Make an attempt to flatten the buffer to reduce access time. |
buffer = buffer->TryFlattenGetString(); |
+ // TODO(1626): For now slicing external strings is not supported. However, |
+ // a flat cons string can have an external string as first part in some cases. |
+ // Therefore we have to single out this case as well. |
+ if (!FLAG_string_slices || |
+ (buffer->IsConsString() && |
+ (!buffer->IsFlat() || |
+ !ConsString::cast(buffer)->first()->IsSeqString())) || |
+ buffer->IsExternalString() || |
+ length < SlicedString::kMinLength || |
+ pretenure == TENURED) { |
+ Object* result; |
+ { MaybeObject* maybe_result = buffer->IsAsciiRepresentation() |
+ ? AllocateRawAsciiString(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 (buffer->IsAsciiRepresentation()) { |
+ ASSERT(string_result->IsAsciiRepresentation()); |
+ char* dest = SeqAsciiString::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()); |
+ ASSERT(!buffer->IsExternalString()); |
+#if DEBUG |
+ buffer->StringVerify(); |
+#endif |
+ |
Object* result; |
- { MaybeObject* maybe_result = buffer->IsAsciiRepresentation() |
- ? AllocateRawAsciiString(length, pretenure ) |
- : AllocateRawTwoByteString(length, pretenure); |
+ { Map* map = buffer->IsAsciiRepresentation() |
+ ? sliced_ascii_string_map() |
+ : sliced_string_map(); |
+ MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
- String* string_result = String::cast(result); |
- // Copy the characters into the new object. |
- if (buffer->IsAsciiRepresentation()) { |
- ASSERT(string_result->IsAsciiRepresentation()); |
- char* dest = SeqAsciiString::cast(string_result)->GetChars(); |
- String::WriteToFlat(buffer, dest, start, end); |
+ |
+ AssertNoAllocation 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 { |
- ASSERT(string_result->IsTwoByteRepresentation()); |
- uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); |
- String::WriteToFlat(buffer, dest, start, end); |
+ sliced_string->set_parent(buffer); |
+ sliced_string->set_offset(start); |
} |
- |
+ ASSERT(sliced_string->parent()->IsSeqString()); |
return result; |
} |