Commit db883422 authored by jshin's avatar jshin Committed by Commit bot

Move lang-code checking for case-mapping to C++ from JS

Move the language code checking for 4 languages requiring
special case mapping to C++ from JavaScript.

This is a speculative fix for crashes reported from Windows and
Mac Chrome canary builds when icu-case-mapping is enabled by
default. (see crbug.com/676643)

In addition, tighten up comparision operators in a couple of
places in i18n.js (=== and !== instead of == and !=).

BUG=v8:4477, v8:4476, chromium:676643
TEST=test262/{built-ins,intl402}/Strings/*, webkit/fast/js/*,
     mjsunit/string-case, intl/general/case*

Review-Url: https://codereview.chromium.org/2621393002
Cr-Commit-Position: refs/heads/master@{#42246}
parent 84d3abe3
......@@ -1124,7 +1124,7 @@ AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false);
* For example \u00DFP (Eszett+P) becomes SSP.
*/
function isWellFormedCurrencyCode(currency) {
return typeof currency == "string" && currency.length == 3 &&
return typeof currency === "string" && currency.length === 3 &&
IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency));
}
......@@ -2029,18 +2029,11 @@ function LocaleConvertCase(s, locales, isToUpper) {
// StringSplit is slower than this.
var pos = %StringIndexOf(language, '-', 0);
if (pos != -1) {
if (pos !== -1) {
language = %_Call(StringSubstring, language, 0, pos);
}
var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr'];
var langIndex = %ArrayIndexOf(CUSTOM_CASE_LANGUAGES, language, 0);
if (langIndex == -1) {
// language-independent case conversion.
return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s);
}
return %StringLocaleConvertCase(s, isToUpper,
CUSTOM_CASE_LANGUAGES[langIndex]);
return %StringLocaleConvertCase(s, isToUpper, language);
}
/**
......
......@@ -1010,21 +1010,14 @@ inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) {
return length;
}
} // namespace
RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
int length = s->length();
s = String::Flatten(s);
MUST_USE_RESULT Object* ConvertToLower(Handle<String> s, Isolate* isolate) {
if (!s->HasOnlyOneByteChars()) {
// Use a slower implementation for strings with characters beyond U+00FF.
return LocaleConvertCase(s, isolate, false, "");
}
int length = s->length();
// We depend here on the invariant that the length of a Latin1
// string is invariant under ToLowerCase, and the result always
// fits in the Latin1 range in the *root locale*. It does not hold
......@@ -1080,14 +1073,8 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
return *result;
}
RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
MUST_USE_RESULT Object* ConvertToUpper(Handle<String> s, Isolate* isolate) {
int32_t length = s->length();
s = String::Flatten(s);
if (s->HasOnlyOneByteChars() && length > 0) {
Handle<SeqOneByteString> result =
isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
......@@ -1147,26 +1134,65 @@ RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
return LocaleConvertCase(s, isolate, true, "");
}
MUST_USE_RESULT Object* ConvertCase(Handle<String> s, bool is_upper,
Isolate* isolate) {
return is_upper ? ConvertToUpper(s, isolate) : ConvertToLower(s, isolate);
}
} // namespace
RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
s = String::Flatten(s);
return ConvertToLower(s, isolate);
}
RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
s = String::Flatten(s);
return ConvertToUpper(s, isolate);
}
RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 3);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1);
CONVERT_ARG_HANDLE_CHECKED(SeqOneByteString, lang, 2);
// All the languages requiring special handling ("az", "el", "lt", "tr")
// have a 2-letter language code.
DCHECK(lang->length() == 2);
uint8_t lang_str[3];
memcpy(lang_str, lang->GetChars(), 2);
lang_str[2] = 0;
CONVERT_ARG_HANDLE_CHECKED(String, lang_arg, 2);
DCHECK(lang_arg->length() <= 3);
lang_arg = String::Flatten(lang_arg);
// All the languages requiring special-handling have two-letter codes.
if (V8_UNLIKELY(lang_arg->length() > 2))
return ConvertCase(s, is_upper, isolate);
char c1, c2;
{
DisallowHeapAllocation no_gc;
String::FlatContent lang = lang_arg->GetFlatContent();
c1 = lang.Get(0);
c2 = lang.Get(1);
}
s = String::Flatten(s);
// TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath
// in the root locale needs to be adjusted for az, lt and tr because even case
// mapping of ASCII range characters are different in those locales.
// Greek (el) does not require any adjustment, though.
return LocaleConvertCase(s, isolate, is_upper,
reinterpret_cast<const char*>(lang_str));
// Greek (el) does not require any adjustment.
if (V8_UNLIKELY(c1 == 't' && c2 == 'r'))
return LocaleConvertCase(s, isolate, is_upper, "tr");
if (V8_UNLIKELY(c1 == 'e' && c2 == 'l'))
return LocaleConvertCase(s, isolate, is_upper, "el");
if (V8_UNLIKELY(c1 == 'l' && c2 == 't'))
return LocaleConvertCase(s, isolate, is_upper, "lt");
if (V8_UNLIKELY(c1 == 'a' && c2 == 'z'))
return LocaleConvertCase(s, isolate, is_upper, "az");
return ConvertCase(s, is_upper, isolate);
}
RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment