diff --git a/src/heap.cc b/src/heap.cc index 34201996b0..9029819fd1 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -1400,6 +1400,10 @@ Object* Heap::AllocateSlicedString(String* buffer, int start, int end) { Object* Heap::AllocateSubString(String* buffer, int start, int end) { int length = end - start; + if (length == 1) { + return Heap::LookupSingleCharacterStringFromCode(buffer->Get(start)); + } + // Make an attempt to flatten the buffer to reduce access time. buffer->TryFlatten(); @@ -1410,9 +1414,19 @@ Object* Heap::AllocateSubString(String* buffer, int start, int end) { // Copy the characters into the new object. String* string_result = String::cast(result); - for (int i = 0; i < length; i++) { - string_result->Set(i, buffer->Get(start + i)); + StringHasher hasher(length); + int i = 0; + for (; i < length && hasher.is_array_index(); i++) { + uc32 c = buffer->Get(start + i); + hasher.AddCharacter(c); + string_result->Set(i, c); } + for (; i < length; i++) { + uc32 c = buffer->Get(start + i); + hasher.AddCharacterNoIndex(c); + string_result->Set(i, c); + } + string_result->set_length_field(hasher.GetHashField()); return result; } diff --git a/src/objects.cc b/src/objects.cc index 1b3e6d001e..c5399fa137 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -527,17 +527,7 @@ Object* String::Flatten() { Heap::AllocateRawTwoByteString(len, tenure); if (object->IsFailure()) return object; String* result = String::cast(object); - StringHasher hasher(len); - Flatten(this, result, 0, len, 0, &hasher); - if (hasher.is_valid()) { -#ifdef DEBUG - result->ComputeAndSetHash(); - ASSERT(result->length_field() == hasher.GetHashField()); -#else - result->set_length_field(hasher.GetHashField()); -#endif - Heap::LookupSymbolIfExists(result, &result); - } + Flatten(this, result, 0, len, 0); cs->set_first(result); cs->set_second(Heap::empty_string()); return this; @@ -3621,8 +3611,7 @@ void String::Flatten(String* src, String* sink, int f, int t, - int so, - StringHasher* hasher) { + int so) { String* source = src; int from = f; int to = t; @@ -3638,8 +3627,6 @@ void String::Flatten(String* src, int j = sink_offset; for (int i = from; i < to; i++) { uc32 c = buffer->GetNext(); - if (hasher->is_valid()) - hasher->AddCharacter(c); sink->Set(j++, c); } return; @@ -3659,7 +3646,7 @@ void String::Flatten(String* src, if (to - boundary >= boundary - from) { // Right hand side is longer. Recurse over left. if (from < boundary) { - Flatten(first, sink, from, boundary, sink_offset, hasher); + Flatten(first, sink, from, boundary, sink_offset); sink_offset += boundary - from; from = 0; } else { @@ -3671,15 +3658,13 @@ void String::Flatten(String* src, // Left hand side is longer. Recurse over right. The hasher // needs us to visit the string from left to right so doing // this invalidates that hash. - hasher->invalidate(); if (to > boundary) { String* second = String::cast(cons_string->second()); Flatten(second, sink, 0, to - boundary, - sink_offset + boundary - from, - hasher); + sink_offset + boundary - from); to = boundary; } source = first; diff --git a/src/objects.h b/src/objects.h index b1aa550079..d21ad65d75 100644 --- a/src/objects.h +++ b/src/objects.h @@ -3077,8 +3077,7 @@ class String: public HeapObject { String* sink, int from, int to, - int sink_offset, - StringHasher* hasher); + int sink_offset); protected: class ReadBlockBuffer { diff --git a/src/runtime.cc b/src/runtime.cc index 2b0b2cd0c4..92e23301b7 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -2404,24 +2404,21 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { if (object->IsFailure()) return object; String* answer = String::cast(object); - StringHasher hasher(length); for (int i = 0; i < array_length; i++) { Object* element = fixed_array->get(i); if (element->IsSmi()) { int len = Smi::cast(element)->value(); int pos = len >> 11; len &= 0x7ff; - String::Flatten(special, answer, pos, pos + len, position, &hasher); + String::Flatten(special, answer, pos, pos + len, position); position += len; } else { String* string = String::cast(element); int element_length = string->length(); - String::Flatten(string, answer, 0, element_length, position, &hasher); + String::Flatten(string, answer, 0, element_length, position); position += element_length; } } - if (hasher.is_valid()) - answer->set_length_field(hasher.GetHashField()); return answer; }