Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 #ifdef V8_I18N_SUPPORT | 6 #ifdef V8_I18N_SUPPORT |
| 7 #include "src/runtime/runtime-utils.h" | 7 #include "src/runtime/runtime-utils.h" |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1003 inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) { | 1003 inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) { |
| 1004 for (int index = 0; index < length; ++index) { | 1004 for (int index = 0; index < length; ++index) { |
| 1005 uint16_t ch = s->Get(index); | 1005 uint16_t ch = s->Get(index); |
| 1006 if (V8_UNLIKELY(IsASCIIUpper(ch) || ch & ~0x7F)) { | 1006 if (V8_UNLIKELY(IsASCIIUpper(ch) || ch & ~0x7F)) { |
| 1007 return index; | 1007 return index; |
| 1008 } | 1008 } |
| 1009 } | 1009 } |
| 1010 return length; | 1010 return length; |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 } // namespace | 1013 MUST_USE_RESULT Object* ConvertToLower(Handle<String> s, Isolate* isolate) { |
| 1014 | |
| 1015 RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) { | |
| 1016 HandleScope scope(isolate); | |
| 1017 DCHECK_EQ(args.length(), 1); | |
| 1018 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); | |
| 1019 | |
| 1020 int length = s->length(); | |
| 1021 s = String::Flatten(s); | |
| 1022 | |
| 1023 if (!s->HasOnlyOneByteChars()) { | 1014 if (!s->HasOnlyOneByteChars()) { |
| 1024 // Use a slower implementation for strings with characters beyond U+00FF. | 1015 // Use a slower implementation for strings with characters beyond U+00FF. |
| 1025 return LocaleConvertCase(s, isolate, false, ""); | 1016 return LocaleConvertCase(s, isolate, false, ""); |
| 1026 } | 1017 } |
| 1027 | 1018 |
| 1019 int length = s->length(); | |
| 1020 | |
| 1028 // We depend here on the invariant that the length of a Latin1 | 1021 // We depend here on the invariant that the length of a Latin1 |
| 1029 // string is invariant under ToLowerCase, and the result always | 1022 // string is invariant under ToLowerCase, and the result always |
| 1030 // fits in the Latin1 range in the *root locale*. It does not hold | 1023 // fits in the Latin1 range in the *root locale*. It does not hold |
| 1031 // for ToUpperCase even in the root locale. | 1024 // for ToUpperCase even in the root locale. |
| 1032 | 1025 |
| 1033 // Scan the string for uppercase and non-ASCII characters for strings | 1026 // Scan the string for uppercase and non-ASCII characters for strings |
| 1034 // shorter than a machine-word without any memory allocation overhead. | 1027 // shorter than a machine-word without any memory allocation overhead. |
| 1035 // TODO(jshin): Apply this to a longer input by breaking FastAsciiConvert() | 1028 // TODO(jshin): Apply this to a longer input by breaking FastAsciiConvert() |
| 1036 // to two parts, one for scanning the prefix with no change and the other for | 1029 // to two parts, one for scanning the prefix with no change and the other for |
| 1037 // handling ASCII-only characters. | 1030 // handling ASCII-only characters. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 const uint16_t* src = flat.ToUC16Vector().start(); | 1066 const uint16_t* src = flat.ToUC16Vector().start(); |
| 1074 CopyChars(dest, src, index_to_first_unprocessed); | 1067 CopyChars(dest, src, index_to_first_unprocessed); |
| 1075 for (int index = index_to_first_unprocessed; index < length; ++index) { | 1068 for (int index = index_to_first_unprocessed; index < length; ++index) { |
| 1076 dest[index] = ToLatin1Lower(static_cast<uint16_t>(src[index])); | 1069 dest[index] = ToLatin1Lower(static_cast<uint16_t>(src[index])); |
| 1077 } | 1070 } |
| 1078 } | 1071 } |
| 1079 | 1072 |
| 1080 return *result; | 1073 return *result; |
| 1081 } | 1074 } |
| 1082 | 1075 |
| 1083 RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) { | 1076 MUST_USE_RESULT Object* ConvertToUpper(Handle<String> s, Isolate* isolate) { |
| 1084 HandleScope scope(isolate); | |
| 1085 DCHECK_EQ(args.length(), 1); | |
| 1086 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); | |
| 1087 | |
| 1088 int32_t length = s->length(); | 1077 int32_t length = s->length(); |
| 1089 s = String::Flatten(s); | |
| 1090 | |
| 1091 if (s->HasOnlyOneByteChars() && length > 0) { | 1078 if (s->HasOnlyOneByteChars() && length > 0) { |
| 1092 Handle<SeqOneByteString> result = | 1079 Handle<SeqOneByteString> result = |
| 1093 isolate->factory()->NewRawOneByteString(length).ToHandleChecked(); | 1080 isolate->factory()->NewRawOneByteString(length).ToHandleChecked(); |
| 1094 | 1081 |
| 1095 int sharp_s_count; | 1082 int sharp_s_count; |
| 1096 bool is_result_single_byte; | 1083 bool is_result_single_byte; |
| 1097 { | 1084 { |
| 1098 DisallowHeapAllocation no_gc; | 1085 DisallowHeapAllocation no_gc; |
| 1099 String::FlatContent flat = s->GetFlatContent(); | 1086 String::FlatContent flat = s->GetFlatContent(); |
| 1100 uint8_t* dest = result->GetChars(); | 1087 uint8_t* dest = result->GetChars(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1140 } else { | 1127 } else { |
| 1141 ToUpperWithSharpS(flat.ToUC16Vector(), result); | 1128 ToUpperWithSharpS(flat.ToUC16Vector(), result); |
| 1142 } | 1129 } |
| 1143 | 1130 |
| 1144 return *result; | 1131 return *result; |
| 1145 } | 1132 } |
| 1146 | 1133 |
| 1147 return LocaleConvertCase(s, isolate, true, ""); | 1134 return LocaleConvertCase(s, isolate, true, ""); |
| 1148 } | 1135 } |
| 1149 | 1136 |
| 1137 MUST_USE_RESULT Object* ConvertCase(Handle<String> s, bool is_upper, | |
| 1138 Isolate* isolate) { | |
| 1139 return is_upper ? ConvertToUpper(s, isolate) : ConvertToLower(s, isolate); | |
| 1140 } | |
| 1141 | |
| 1142 } // namespace | |
| 1143 | |
| 1144 RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) { | |
| 1145 HandleScope scope(isolate); | |
| 1146 DCHECK_EQ(args.length(), 1); | |
| 1147 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); | |
| 1148 s = String::Flatten(s); | |
| 1149 return ConvertToLower(s, isolate); | |
| 1150 } | |
| 1151 | |
| 1152 RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) { | |
| 1153 HandleScope scope(isolate); | |
| 1154 DCHECK_EQ(args.length(), 1); | |
| 1155 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); | |
| 1156 s = String::Flatten(s); | |
| 1157 return ConvertToUpper(s, isolate); | |
| 1158 } | |
| 1159 | |
| 1150 RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) { | 1160 RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) { |
| 1151 HandleScope scope(isolate); | 1161 HandleScope scope(isolate); |
| 1152 DCHECK_EQ(args.length(), 3); | 1162 DCHECK_EQ(args.length(), 3); |
| 1153 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); | 1163 CONVERT_ARG_HANDLE_CHECKED(String, s, 0); |
| 1154 CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); | 1164 CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); |
| 1155 CONVERT_ARG_HANDLE_CHECKED(SeqOneByteString, lang, 2); | 1165 CONVERT_ARG_HANDLE_CHECKED(String, lang_arg, 2); |
|
jungshik at Google
2017/01/11 19:11:22
From i18n.js, a string "literal" ( e.g. "el", "tr"
| |
| 1156 | 1166 |
| 1157 // All the languages requiring special handling ("az", "el", "lt", "tr") | 1167 DCHECK(lang_arg->length() <= 3); |
| 1158 // have a 2-letter language code. | 1168 lang_arg = String::Flatten(lang_arg); |
| 1159 DCHECK(lang->length() == 2); | 1169 |
| 1160 uint8_t lang_str[3]; | 1170 // All the languages requiring special-handling have two-letter codes. |
| 1161 memcpy(lang_str, lang->GetChars(), 2); | 1171 if (V8_UNLIKELY(lang_arg->length() > 2)) |
| 1162 lang_str[2] = 0; | 1172 return ConvertCase(s, is_upper, isolate); |
| 1173 | |
| 1174 char c1, c2; | |
| 1175 { | |
| 1176 DisallowHeapAllocation no_gc; | |
| 1177 String::FlatContent lang = lang_arg->GetFlatContent(); | |
| 1178 c1 = lang.Get(0); | |
| 1179 c2 = lang.Get(1); | |
| 1180 } | |
| 1163 s = String::Flatten(s); | 1181 s = String::Flatten(s); |
| 1164 // TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath | 1182 // TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath |
| 1165 // in the root locale needs to be adjusted for az, lt and tr because even case | 1183 // in the root locale needs to be adjusted for az, lt and tr because even case |
| 1166 // mapping of ASCII range characters are different in those locales. | 1184 // mapping of ASCII range characters are different in those locales. |
| 1167 // Greek (el) does not require any adjustment, though. | 1185 // Greek (el) does not require any adjustment. |
| 1168 return LocaleConvertCase(s, isolate, is_upper, | 1186 if (V8_UNLIKELY(c1 == 't' && c2 == 'r')) |
| 1169 reinterpret_cast<const char*>(lang_str)); | 1187 return LocaleConvertCase(s, isolate, is_upper, "tr"); |
| 1188 if (V8_UNLIKELY(c1 == 'e' && c2 == 'l')) | |
| 1189 return LocaleConvertCase(s, isolate, is_upper, "el"); | |
| 1190 if (V8_UNLIKELY(c1 == 'l' && c2 == 't')) | |
| 1191 return LocaleConvertCase(s, isolate, is_upper, "lt"); | |
| 1192 if (V8_UNLIKELY(c1 == 'a' && c2 == 'z')) | |
| 1193 return LocaleConvertCase(s, isolate, is_upper, "az"); | |
| 1194 | |
| 1195 return ConvertCase(s, is_upper, isolate); | |
| 1170 } | 1196 } |
| 1171 | 1197 |
| 1172 RUNTIME_FUNCTION(Runtime_DateCacheVersion) { | 1198 RUNTIME_FUNCTION(Runtime_DateCacheVersion) { |
| 1173 HandleScope scope(isolate); | 1199 HandleScope scope(isolate); |
| 1174 DCHECK_EQ(0, args.length()); | 1200 DCHECK_EQ(0, args.length()); |
| 1175 if (isolate->serializer_enabled()) return isolate->heap()->undefined_value(); | 1201 if (isolate->serializer_enabled()) return isolate->heap()->undefined_value(); |
| 1176 if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) { | 1202 if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) { |
| 1177 Handle<FixedArray> date_cache_version = | 1203 Handle<FixedArray> date_cache_version = |
| 1178 isolate->factory()->NewFixedArray(1, TENURED); | 1204 isolate->factory()->NewFixedArray(1, TENURED); |
| 1179 date_cache_version->set(0, Smi::kZero); | 1205 date_cache_version->set(0, Smi::kZero); |
| 1180 isolate->eternal_handles()->CreateSingleton( | 1206 isolate->eternal_handles()->CreateSingleton( |
| 1181 isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION); | 1207 isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION); |
| 1182 } | 1208 } |
| 1183 Handle<FixedArray> date_cache_version = | 1209 Handle<FixedArray> date_cache_version = |
| 1184 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton( | 1210 Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton( |
| 1185 EternalHandles::DATE_CACHE_VERSION)); | 1211 EternalHandles::DATE_CACHE_VERSION)); |
| 1186 return date_cache_version->get(0); | 1212 return date_cache_version->get(0); |
| 1187 } | 1213 } |
| 1188 | 1214 |
| 1189 } // namespace internal | 1215 } // namespace internal |
| 1190 } // namespace v8 | 1216 } // namespace v8 |
| 1191 | 1217 |
| 1192 #endif // V8_I18N_SUPPORT | 1218 #endif // V8_I18N_SUPPORT |
| OLD | NEW |