Index: src/objects.cc |
=================================================================== |
--- src/objects.cc (revision 9658) |
+++ 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; |
+ 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(); |