Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: src/heap.cc

Issue 2762008: Track ascii-ness of data in externalized strings. (Closed)
Patch Set: Extended tests. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/ia32/codegen-ia32.cc » ('j') | src/objects-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698