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 |