Chromium Code Reviews| Index: src/objects.cc |
| =================================================================== |
| --- src/objects.cc (revision 9640) |
| +++ src/objects.cc (working copy) |
| @@ -5519,24 +5519,6 @@ |
| } |
| -int String::Utf8Length() { |
| - if (IsAsciiRepresentation()) return length(); |
| - // Attempt to flatten before accessing the string. It probably |
| - // doesn't make Utf8Length faster, but it is very likely that |
| - // the string will be accessed later (for example by WriteUtf8) |
| - // so it's still a good idea. |
| - Heap* heap = GetHeap(); |
| - TryFlatten(); |
| - Access<StringInputBuffer> buffer( |
| - heap->isolate()->objects_string_input_buffer()); |
| - buffer->Reset(0, this); |
| - int result = 0; |
| - while (buffer->has_more()) |
| - result += unibrow::Utf8::Length(buffer->GetNext()); |
| - return result; |
| -} |
| - |
| - |
| String::FlatContent String::GetFlatContent() { |
| int length = this->length(); |
| StringShape shape(this); |
| @@ -5960,6 +5942,73 @@ |
| } |
| +// This method determines the type of string involved and then gets the UTF8 |
| +// length of the string. It doesn't flatten the string and has log(n) recursion |
| +// for a string of length n. |
| +int String::Utf8Length(String* input, int from, int to) { |
| + if (from == to) return 0; |
| + int total = 0; |
| + while (true) { |
| + if (input->IsAsciiRepresentation()) return total + to - from; |
|
Yang
2011/10/17 09:40:51
Again, IsAsciiRepresentation() is not reliable.
Erik Corry
2011/10/17 12:39:09
I think in this case it is exactly what I need. I
|
| + switch (StringShape(input).representation_tag()) { |
| + case kConsStringTag: { |
| + ConsString* str = ConsString::cast(input); |
| + String* first = str->first(); |
| + String* second = str->second(); |
| + int first_length = first->length(); |
| + if (first_length - from < to - first_length) { |
| + if (first_length > from) { |
| + // Left hand side is shorter. |
| + total += Utf8Length(first, from, first_length); |
| + input = second; |
| + from = 0; |
| + to -= first_length; |
| + } else { |
| + // We only need the right hand side. |
| + input = second; |
| + from -= first_length; |
| + to -= first_length; |
| + } |
| + } else { |
| + if (first_length > to) { |
| + // Right hand side is shorter. |
| + total += Utf8Length(second, 0, to - first_length); |
| + input = first; |
| + to = first_length; |
| + } else { |
| + // We only need the left hand side. |
| + input = first; |
| + } |
| + } |
| + continue; |
| + } |
| + case kExternalStringTag: |
| + case kSeqStringTag: { |
| + Vector<const uc16> vector = input->GetFlatContent().ToUC16Vector(); |
| + const uc16* p = vector.start(); |
| + for (int i = from; i < to; i++) { |
| + total += unibrow::Utf8::Length(p[i]); |
| + } |
| + return total; |
| + } |
| + case kSlicedStringTag: { |
| + SlicedString* str = SlicedString::cast(input); |
| + int offset = str->offset(); |
| + input = str->parent(); |
| + from += offset; |
| + to += offset; |
| + continue; |
| + } |
| + default: |
| + break; |
| + } |
| + UNREACHABLE(); |
| + return 0; |
| + } |
| + return 0; |
| +} |
| + |
| + |
| void Relocatable::PostGarbageCollectionProcessing() { |
| Isolate* isolate = Isolate::Current(); |
| Relocatable* current = isolate->relocatable_top(); |