| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index 3115cb31d60b9af9367379dc5b09b3d52a9d3dc0..1464949559431e478226a24f70fbfe78e8292420 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -1927,6 +1927,18 @@ Object* Heap::AllocateConsString(String* first, String* second) {
|
| return Failure::OutOfMemoryException();
|
| }
|
|
|
| + bool is_ascii_data_in_two_byte_string = false;
|
| + if (!is_ascii) {
|
| + // At least one of the strings uses two-byte representation so we
|
| + // can't use the fast case code for short ascii strings below, but
|
| + // we can try to save memory if all chars actually fit in ascii.
|
| + is_ascii_data_in_two_byte_string =
|
| + first->HasAsciiChars() && second->HasAsciiChars();
|
| + if (is_ascii_data_in_two_byte_string) {
|
| + Counters::string_add_runtime_ext_to_ascii.Increment();
|
| + }
|
| + }
|
| +
|
| // If the resulting string is small make a flat string.
|
| if (length < String::kMinNonFlatLength) {
|
| ASSERT(first->IsFlat());
|
| @@ -1953,22 +1965,13 @@ Object* Heap::AllocateConsString(String* first, String* second) {
|
| for (int i = 0; i < second_length; i++) *dest++ = src[i];
|
| return result;
|
| } else {
|
| - // For short external two-byte strings we check whether they can
|
| - // be represented using ascii.
|
| - if (!first_is_ascii) {
|
| - first_is_ascii = first->IsExternalTwoByteStringWithAsciiChars();
|
| - }
|
| - if (first_is_ascii && !second_is_ascii) {
|
| - second_is_ascii = second->IsExternalTwoByteStringWithAsciiChars();
|
| - }
|
| - if (first_is_ascii && second_is_ascii) {
|
| + if (is_ascii_data_in_two_byte_string) {
|
| Object* result = AllocateRawAsciiString(length);
|
| if (result->IsFailure()) return result;
|
| // Copy the characters into the new object.
|
| char* dest = SeqAsciiString::cast(result)->GetChars();
|
| String::WriteToFlat(first, dest, 0, first_length);
|
| String::WriteToFlat(second, dest + first_length, 0, second_length);
|
| - Counters::string_add_runtime_ext_to_ascii.Increment();
|
| return result;
|
| }
|
|
|
| @@ -1982,7 +1985,8 @@ Object* Heap::AllocateConsString(String* first, String* second) {
|
| }
|
| }
|
|
|
| - Map* map = is_ascii ? cons_ascii_string_map() : cons_string_map();
|
| + Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ?
|
| + cons_ascii_string_map() : cons_string_map();
|
|
|
| Object* result = Allocate(map, NEW_SPACE);
|
| if (result->IsFailure()) return result;
|
| @@ -2068,7 +2072,23 @@ Object* Heap::AllocateExternalStringFromTwoByte(
|
| return Failure::OutOfMemoryException();
|
| }
|
|
|
| - Map* map = Heap::external_string_map();
|
| + // For small strings we check whether the resource contains only
|
| + // ascii characters. If yes, we use a different string map.
|
| + bool is_ascii = true;
|
| + if (length >= static_cast<size_t>(String::kMinNonFlatLength)) {
|
| + is_ascii = false;
|
| + } else {
|
| + const uc16* data = resource->data();
|
| + for (size_t i = 0; i < length; i++) {
|
| + if (data[i] > String::kMaxAsciiCharCode) {
|
| + is_ascii = false;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + Map* map = is_ascii ?
|
| + Heap::external_string_with_ascii_data_map() : Heap::external_string_map();
|
| Object* result = Allocate(map, NEW_SPACE);
|
| if (result->IsFailure()) return result;
|
|
|
| @@ -2851,6 +2871,9 @@ Map* Heap::SymbolMapForString(String* string) {
|
| if (map == cons_ascii_string_map()) return cons_ascii_symbol_map();
|
| if (map == external_string_map()) return external_symbol_map();
|
| if (map == external_ascii_string_map()) return external_ascii_symbol_map();
|
| + if (map == external_string_with_ascii_data_map()) {
|
| + return external_symbol_with_ascii_data_map();
|
| + }
|
|
|
| // No match found.
|
| return NULL;
|
|
|