Chromium Code Reviews| Index: src/objects.cc |
| =================================================================== |
| --- src/objects.cc (revision 535) |
| +++ src/objects.cc (working copy) |
| @@ -528,12 +528,28 @@ |
| // an old space GC. |
| PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; |
| int len = length(); |
| - Object* object = IsAsciiRepresentation() ? |
| - Heap::AllocateRawAsciiString(len, tenure) : |
| - Heap::AllocateRawTwoByteString(len, tenure); |
| - if (object->IsFailure()) return object; |
| - String* result = String::cast(object); |
| - Flatten(this, result, 0, len, 0); |
| + Object* object; |
| + String* result; |
| + if (IsAsciiRepresentation()) { |
| + object = Heap::AllocateRawAsciiString(len, tenure); |
| + if (object->IsFailure()) return object; |
| + result = String::cast(object); |
| + String* first = String::cast(cs->first()); |
| + int first_length = first->length(); |
| + byte* dest = SeqAsciiString::cast(result)->GetCharsAddress(); |
| + WriteToFlat(first, dest, 0, first_length); |
| + WriteToFlat(String::cast(cs->second()), dest + first_length, 0, len - first_length); |
| + } else { |
| + object = Heap::AllocateRawTwoByteString(len, tenure); |
| + if (object->IsFailure()) return object; |
| + result = String::cast(object); |
| + uc16* dest = reinterpret_cast<uc16*>( |
| + SeqTwoByteString::cast(result)->GetCharsAddress()); |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Maybe add an accessor on seq two byte string that
Erik Corry
2008/10/22 11:59:48
Good idea.
|
| + String* first = String::cast(cs->first()); |
| + int first_length = first->length(); |
| + WriteToFlat(first, dest, 0, first_length); |
| + WriteToFlat(String::cast(cs->second()), dest + first_length, 0, len - first_length); |
| + } |
| cs->set_first(result); |
| cs->set_second(Heap::empty_string()); |
| return this; |
| @@ -2869,7 +2885,7 @@ |
| } |
| -Vector<const char> String::ToAsciiVector() { |
| +Vector<const byte> String::ToAsciiVector() { |
| ASSERT(IsAsciiRepresentation()); |
| ASSERT(IsFlat()); |
| @@ -2890,13 +2906,13 @@ |
| } |
| if (string_tag == kSeqStringTag) { |
| SeqAsciiString* seq = SeqAsciiString::cast(string); |
| - char* start = reinterpret_cast<char*>(seq->GetCharsAddress()); |
| - return Vector<const char>(start + offset, length); |
| + byte* start = seq->GetCharsAddress(); |
| + return Vector<const byte>(start + offset, length); |
| } |
| ASSERT(string_tag == kExternalStringTag); |
| ExternalAsciiString* ext = ExternalAsciiString::cast(string); |
| - const char* start = ext->resource()->data(); |
| - return Vector<const char>(start + offset, length); |
| + const byte* start = reinterpret_cast<const byte*>(ext->resource()->data()); |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Bleh. Why not stick with char?
Erik Corry
2008/10/22 11:59:48
Done
|
| + return Vector<const byte>(start + offset, length); |
| } |
| @@ -3557,47 +3573,87 @@ |
| } |
| -void String::Flatten(String* src, |
| - String* sink, |
| - int f, |
| - int t, |
| - int so) { |
| +// Assumes that if the sink is ASCII then the src will also be ASCII |
| +// representation (not just ASCII in a 16 bit string). |
| +template <typename sinkchar> |
| +void String::WriteToFlat(String* src, |
| + sinkchar* sink, |
| + int f, |
| + int t) { |
| String* source = src; |
| int from = f; |
| int to = t; |
| - int sink_offset = so; |
| while (true) { |
| ASSERT(0 <= from && from <= to && to <= source->length()); |
| - ASSERT(0 <= sink_offset && sink_offset < sink->length()); |
| - switch (source->representation_tag()) { |
| - case kSeqStringTag: |
| - case kExternalStringTag: { |
| - Access<StringInputBuffer> buffer(&string_input_buffer); |
| - buffer->Reset(from, source); |
| - int j = sink_offset; |
| - for (int i = from; i < to; i++) { |
| - uc32 c = buffer->GetNext(); |
| - sink->Set(j++, c); |
| + switch (source->full_representation_tag()) { |
| + case kAsciiStringTag + kExternalStringTag: { |
| + if (sizeof(sinkchar) == 1) { |
| + memcpy( |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Could this be simplified by using a template-ified
Erik Corry
2008/10/22 11:59:48
Done.
|
| + sink, |
| + ExternalAsciiString::cast(source)->resource()->data() + from, |
| + to - from); |
| + } else { |
| + Cpy168( |
| + sink, |
| + // Sign cast. |
| + reinterpret_cast<const byte*>( |
| + ExternalAsciiString::cast(source)->resource()->data()) + |
| + from, |
| + to - from); |
| } |
| return; |
| } |
| - case kSlicedStringTag: { |
| + case kTwoByteStringTag + kExternalStringTag: { |
|
Christian Plesner Hansen
2008/10/21 14:16:22
If | gives the same result as + we should use that
Erik Corry
2008/10/22 11:59:48
Done
|
| + ASSERT(sizeof(sinkchar) == 2); |
| + memcpy( |
| + sink, |
| + ExternalTwoByteString::cast(source)->resource()->data() + (from << 1), |
| + (to - from) << 1); |
| + return; |
| + } |
| + case kAsciiStringTag + kSeqStringTag: { |
| + if (sizeof(sinkchar) == 1) { |
| + const byte* src = |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Isn't this the branch where we can memcpy? Source
Erik Corry
2008/10/22 11:59:48
The non-memcpy may be marginally faster, but this
|
| + SeqAsciiString::cast(source)->GetCharsAddress() + from; |
| + const byte* end = src - from + to; |
| + while (src < end) { |
| + *sink++ = *src++; |
| + } |
| + } else { |
| + Cpy168( |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Conversely, this looks to me like we're memcpying
Erik Corry
2008/10/22 11:59:48
Gone in new version.
|
| + sink, |
| + SeqAsciiString::cast(source)->GetCharsAddress() + from, |
| + to - from); |
| + } |
| + return; |
| + } |
| + case kTwoByteStringTag + kSeqStringTag: { |
| + ASSERT(sizeof(sinkchar) == 2); |
| + memcpy( |
| + sink, |
| + SeqTwoByteString::cast(source)->GetCharsAddress() + (from << 1), |
| + (to - from) << 1); |
| + return; |
| + } |
| + case kAsciiStringTag + kSlicedStringTag: |
| + case kTwoByteStringTag + kSlicedStringTag: { |
| SlicedString* sliced_string = SlicedString::cast(source); |
| int start = sliced_string->start(); |
| from += start; |
| to += start; |
| source = String::cast(sliced_string->buffer()); |
| + break; |
| } |
| - break; |
| - case kConsStringTag: { |
| + case kAsciiStringTag + kConsStringTag: |
| + case kTwoByteStringTag + kConsStringTag: { |
| ConsString* cons_string = ConsString::cast(source); |
| String* first = String::cast(cons_string->first()); |
| int boundary = first->length(); |
| - if (to - boundary >= boundary - from) { |
| + if (boundary < 64 || to - boundary >= boundary - from) { |
|
Christian Plesner Hansen
2008/10/21 14:16:22
Magic number. Please define a constant.
Erik Corry
2008/10/22 11:59:48
I got rid of this optimization because I found a t
|
| // Right hand side is longer. Recurse over left. |
| if (from < boundary) { |
| - Flatten(first, sink, from, boundary, sink_offset); |
| - sink_offset += boundary - from; |
| + WriteToFlat(first, sink, from, boundary); |
| + sink += boundary - from; |
| from = 0; |
| } else { |
| from -= boundary; |
| @@ -3610,17 +3666,16 @@ |
| // this invalidates that hash. |
| if (to > boundary) { |
| String* second = String::cast(cons_string->second()); |
| - Flatten(second, |
| - sink, |
| - 0, |
| - to - boundary, |
| - sink_offset + boundary - from); |
| + WriteToFlat(second, |
| + sink + boundary - from, |
| + 0, |
| + to - boundary); |
| to = boundary; |
| } |
| source = first; |
| } |
| + break; |
| } |
| - break; |
| } |
| } |
| } |
| @@ -3690,10 +3745,10 @@ |
| static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { |
| if (b->IsFlat()) { |
| if (b->IsAsciiRepresentation()) { |
| - VectorIterator<char> ib(b->ToAsciiVector()); |
| + VectorIterator<const byte> ib(b->ToAsciiVector()); |
|
Christian Plesner Hansen
2008/10/21 14:16:22
There's no need to explicitly add 'const' to a Vec
Erik Corry
2008/10/22 11:59:48
OK
|
| return CompareStringContents(ia, &ib); |
| } else { |
| - VectorIterator<uc16> ib(b->ToUC16Vector()); |
| + VectorIterator<const uc16> ib(b->ToUC16Vector()); |
| return CompareStringContents(ia, &ib); |
| } |
| } else { |
| @@ -3727,18 +3782,18 @@ |
| if (this->IsFlat()) { |
| if (this->IsAsciiRepresentation()) { |
| - Vector<const char> vec1 = this->ToAsciiVector(); |
| + Vector<const byte> vec1 = this->ToAsciiVector(); |
| if (other->IsFlat()) { |
| if (other->IsAsciiRepresentation()) { |
| - Vector<const char> vec2 = other->ToAsciiVector(); |
| + Vector<const byte> vec2 = other->ToAsciiVector(); |
| return CompareRawStringContents(vec1, vec2); |
| } else { |
| - VectorIterator<char> buf1(vec1); |
| - VectorIterator<uc16> ib(other->ToUC16Vector()); |
| + VectorIterator<const byte> buf1(vec1); |
| + VectorIterator<const uc16> ib(other->ToUC16Vector()); |
| return CompareStringContents(&buf1, &ib); |
| } |
| } else { |
| - VectorIterator<char> buf1(vec1); |
| + VectorIterator<const byte> buf1(vec1); |
| string_compare_buffer_b.Reset(0, other); |
| return CompareStringContents(&buf1, &string_compare_buffer_b); |
| } |
| @@ -3746,15 +3801,15 @@ |
| Vector<const uc16> vec1 = this->ToUC16Vector(); |
| if (other->IsFlat()) { |
| if (other->IsAsciiRepresentation()) { |
| - VectorIterator<uc16> buf1(vec1); |
| - VectorIterator<char> ib(other->ToAsciiVector()); |
| + VectorIterator<const uc16> buf1(vec1); |
| + VectorIterator<const byte> ib(other->ToAsciiVector()); |
| return CompareStringContents(&buf1, &ib); |
| } else { |
| Vector<const uc16> vec2(other->ToUC16Vector()); |
| return CompareRawStringContents(vec1, vec2); |
| } |
| } else { |
| - VectorIterator<uc16> buf1(vec1); |
| + VectorIterator<const uc16> buf1(vec1); |
| string_compare_buffer_b.Reset(0, other); |
| return CompareStringContents(&buf1, &string_compare_buffer_b); |
| } |