OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1920 bool second_is_ascii = second->IsAsciiRepresentation(); | 1920 bool second_is_ascii = second->IsAsciiRepresentation(); |
1921 bool is_ascii = first_is_ascii && second_is_ascii; | 1921 bool is_ascii = first_is_ascii && second_is_ascii; |
1922 | 1922 |
1923 // Make sure that an out of memory exception is thrown if the length | 1923 // Make sure that an out of memory exception is thrown if the length |
1924 // of the new cons string is too large. | 1924 // of the new cons string is too large. |
1925 if (length > String::kMaxLength || length < 0) { | 1925 if (length > String::kMaxLength || length < 0) { |
1926 Top::context()->mark_out_of_memory(); | 1926 Top::context()->mark_out_of_memory(); |
1927 return Failure::OutOfMemoryException(); | 1927 return Failure::OutOfMemoryException(); |
1928 } | 1928 } |
1929 | 1929 |
| 1930 bool is_ascii_data_in_two_byte_string = false; |
| 1931 if (!is_ascii) { |
| 1932 // At least one of the strings uses two-byte representation so we |
| 1933 // can't use the fast case code for short ascii strings below, but |
| 1934 // we can try to save memory if all chars actually fit in ascii. |
| 1935 is_ascii_data_in_two_byte_string = |
| 1936 first->HasAsciiChars() && second->HasAsciiChars(); |
| 1937 if (is_ascii_data_in_two_byte_string) { |
| 1938 Counters::string_add_runtime_ext_to_ascii.Increment(); |
| 1939 } |
| 1940 } |
| 1941 |
1930 // If the resulting string is small make a flat string. | 1942 // If the resulting string is small make a flat string. |
1931 if (length < String::kMinNonFlatLength) { | 1943 if (length < String::kMinNonFlatLength) { |
1932 ASSERT(first->IsFlat()); | 1944 ASSERT(first->IsFlat()); |
1933 ASSERT(second->IsFlat()); | 1945 ASSERT(second->IsFlat()); |
1934 if (is_ascii) { | 1946 if (is_ascii) { |
1935 Object* result = AllocateRawAsciiString(length); | 1947 Object* result = AllocateRawAsciiString(length); |
1936 if (result->IsFailure()) return result; | 1948 if (result->IsFailure()) return result; |
1937 // Copy the characters into the new object. | 1949 // Copy the characters into the new object. |
1938 char* dest = SeqAsciiString::cast(result)->GetChars(); | 1950 char* dest = SeqAsciiString::cast(result)->GetChars(); |
1939 // Copy first part. | 1951 // Copy first part. |
1940 const char* src; | 1952 const char* src; |
1941 if (first->IsExternalString()) { | 1953 if (first->IsExternalString()) { |
1942 src = ExternalAsciiString::cast(first)->resource()->data(); | 1954 src = ExternalAsciiString::cast(first)->resource()->data(); |
1943 } else { | 1955 } else { |
1944 src = SeqAsciiString::cast(first)->GetChars(); | 1956 src = SeqAsciiString::cast(first)->GetChars(); |
1945 } | 1957 } |
1946 for (int i = 0; i < first_length; i++) *dest++ = src[i]; | 1958 for (int i = 0; i < first_length; i++) *dest++ = src[i]; |
1947 // Copy second part. | 1959 // Copy second part. |
1948 if (second->IsExternalString()) { | 1960 if (second->IsExternalString()) { |
1949 src = ExternalAsciiString::cast(second)->resource()->data(); | 1961 src = ExternalAsciiString::cast(second)->resource()->data(); |
1950 } else { | 1962 } else { |
1951 src = SeqAsciiString::cast(second)->GetChars(); | 1963 src = SeqAsciiString::cast(second)->GetChars(); |
1952 } | 1964 } |
1953 for (int i = 0; i < second_length; i++) *dest++ = src[i]; | 1965 for (int i = 0; i < second_length; i++) *dest++ = src[i]; |
1954 return result; | 1966 return result; |
1955 } else { | 1967 } else { |
1956 // For short external two-byte strings we check whether they can | 1968 if (is_ascii_data_in_two_byte_string) { |
1957 // be represented using ascii. | |
1958 if (!first_is_ascii) { | |
1959 first_is_ascii = first->IsExternalTwoByteStringWithAsciiChars(); | |
1960 } | |
1961 if (first_is_ascii && !second_is_ascii) { | |
1962 second_is_ascii = second->IsExternalTwoByteStringWithAsciiChars(); | |
1963 } | |
1964 if (first_is_ascii && second_is_ascii) { | |
1965 Object* result = AllocateRawAsciiString(length); | 1969 Object* result = AllocateRawAsciiString(length); |
1966 if (result->IsFailure()) return result; | 1970 if (result->IsFailure()) return result; |
1967 // Copy the characters into the new object. | 1971 // Copy the characters into the new object. |
1968 char* dest = SeqAsciiString::cast(result)->GetChars(); | 1972 char* dest = SeqAsciiString::cast(result)->GetChars(); |
1969 String::WriteToFlat(first, dest, 0, first_length); | 1973 String::WriteToFlat(first, dest, 0, first_length); |
1970 String::WriteToFlat(second, dest + first_length, 0, second_length); | 1974 String::WriteToFlat(second, dest + first_length, 0, second_length); |
1971 Counters::string_add_runtime_ext_to_ascii.Increment(); | |
1972 return result; | 1975 return result; |
1973 } | 1976 } |
1974 | 1977 |
1975 Object* result = AllocateRawTwoByteString(length); | 1978 Object* result = AllocateRawTwoByteString(length); |
1976 if (result->IsFailure()) return result; | 1979 if (result->IsFailure()) return result; |
1977 // Copy the characters into the new object. | 1980 // Copy the characters into the new object. |
1978 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | 1981 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
1979 String::WriteToFlat(first, dest, 0, first_length); | 1982 String::WriteToFlat(first, dest, 0, first_length); |
1980 String::WriteToFlat(second, dest + first_length, 0, second_length); | 1983 String::WriteToFlat(second, dest + first_length, 0, second_length); |
1981 return result; | 1984 return result; |
1982 } | 1985 } |
1983 } | 1986 } |
1984 | 1987 |
1985 Map* map = is_ascii ? cons_ascii_string_map() : cons_string_map(); | 1988 Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ? |
| 1989 cons_ascii_string_map() : cons_string_map(); |
1986 | 1990 |
1987 Object* result = Allocate(map, NEW_SPACE); | 1991 Object* result = Allocate(map, NEW_SPACE); |
1988 if (result->IsFailure()) return result; | 1992 if (result->IsFailure()) return result; |
1989 | 1993 |
1990 AssertNoAllocation no_gc; | 1994 AssertNoAllocation no_gc; |
1991 ConsString* cons_string = ConsString::cast(result); | 1995 ConsString* cons_string = ConsString::cast(result); |
1992 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc); | 1996 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc); |
1993 cons_string->set_length(length); | 1997 cons_string->set_length(length); |
1994 cons_string->set_hash_field(String::kEmptyHashField); | 1998 cons_string->set_hash_field(String::kEmptyHashField); |
1995 cons_string->set_first(first, mode); | 1999 cons_string->set_first(first, mode); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 | 2065 |
2062 | 2066 |
2063 Object* Heap::AllocateExternalStringFromTwoByte( | 2067 Object* Heap::AllocateExternalStringFromTwoByte( |
2064 ExternalTwoByteString::Resource* resource) { | 2068 ExternalTwoByteString::Resource* resource) { |
2065 size_t length = resource->length(); | 2069 size_t length = resource->length(); |
2066 if (length > static_cast<size_t>(String::kMaxLength)) { | 2070 if (length > static_cast<size_t>(String::kMaxLength)) { |
2067 Top::context()->mark_out_of_memory(); | 2071 Top::context()->mark_out_of_memory(); |
2068 return Failure::OutOfMemoryException(); | 2072 return Failure::OutOfMemoryException(); |
2069 } | 2073 } |
2070 | 2074 |
2071 Map* map = Heap::external_string_map(); | 2075 // For small strings we check whether the resource contains only |
| 2076 // ascii characters. If yes, we use a different string map. |
| 2077 bool is_ascii = true; |
| 2078 if (length >= static_cast<size_t>(String::kMinNonFlatLength)) { |
| 2079 is_ascii = false; |
| 2080 } else { |
| 2081 const uc16* data = resource->data(); |
| 2082 for (size_t i = 0; i < length; i++) { |
| 2083 if (data[i] > String::kMaxAsciiCharCode) { |
| 2084 is_ascii = false; |
| 2085 break; |
| 2086 } |
| 2087 } |
| 2088 } |
| 2089 |
| 2090 Map* map = is_ascii ? |
| 2091 Heap::external_string_with_ascii_data_map() : Heap::external_string_map(); |
2072 Object* result = Allocate(map, NEW_SPACE); | 2092 Object* result = Allocate(map, NEW_SPACE); |
2073 if (result->IsFailure()) return result; | 2093 if (result->IsFailure()) return result; |
2074 | 2094 |
2075 ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); | 2095 ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); |
2076 external_string->set_length(static_cast<int>(length)); | 2096 external_string->set_length(static_cast<int>(length)); |
2077 external_string->set_hash_field(String::kEmptyHashField); | 2097 external_string->set_hash_field(String::kEmptyHashField); |
2078 external_string->set_resource(resource); | 2098 external_string->set_resource(resource); |
2079 | 2099 |
2080 return result; | 2100 return result; |
2081 } | 2101 } |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2844 if (InNewSpace(string)) return NULL; | 2864 if (InNewSpace(string)) return NULL; |
2845 | 2865 |
2846 // Find the corresponding symbol map for strings. | 2866 // Find the corresponding symbol map for strings. |
2847 Map* map = string->map(); | 2867 Map* map = string->map(); |
2848 if (map == ascii_string_map()) return ascii_symbol_map(); | 2868 if (map == ascii_string_map()) return ascii_symbol_map(); |
2849 if (map == string_map()) return symbol_map(); | 2869 if (map == string_map()) return symbol_map(); |
2850 if (map == cons_string_map()) return cons_symbol_map(); | 2870 if (map == cons_string_map()) return cons_symbol_map(); |
2851 if (map == cons_ascii_string_map()) return cons_ascii_symbol_map(); | 2871 if (map == cons_ascii_string_map()) return cons_ascii_symbol_map(); |
2852 if (map == external_string_map()) return external_symbol_map(); | 2872 if (map == external_string_map()) return external_symbol_map(); |
2853 if (map == external_ascii_string_map()) return external_ascii_symbol_map(); | 2873 if (map == external_ascii_string_map()) return external_ascii_symbol_map(); |
| 2874 if (map == external_string_with_ascii_data_map()) { |
| 2875 return external_symbol_with_ascii_data_map(); |
| 2876 } |
2854 | 2877 |
2855 // No match found. | 2878 // No match found. |
2856 return NULL; | 2879 return NULL; |
2857 } | 2880 } |
2858 | 2881 |
2859 | 2882 |
2860 Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, | 2883 Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, |
2861 int chars, | 2884 int chars, |
2862 uint32_t hash_field) { | 2885 uint32_t hash_field) { |
2863 ASSERT(chars >= 0); | 2886 ASSERT(chars >= 0); |
(...skipping 1874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4738 void ExternalStringTable::TearDown() { | 4761 void ExternalStringTable::TearDown() { |
4739 new_space_strings_.Free(); | 4762 new_space_strings_.Free(); |
4740 old_space_strings_.Free(); | 4763 old_space_strings_.Free(); |
4741 } | 4764 } |
4742 | 4765 |
4743 | 4766 |
4744 List<Object*> ExternalStringTable::new_space_strings_; | 4767 List<Object*> ExternalStringTable::new_space_strings_; |
4745 List<Object*> ExternalStringTable::old_space_strings_; | 4768 List<Object*> ExternalStringTable::old_space_strings_; |
4746 | 4769 |
4747 } } // namespace v8::internal | 4770 } } // namespace v8::internal |
OLD | NEW |