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); ...@@ -1124,7 +1124,7 @@ AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false);
* For example \u00DFP (Eszett+P) becomes SSP. * For example \u00DFP (Eszett+P) becomes SSP.
*/ */
function isWellFormedCurrencyCode(currency) { 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)); IS_NULL(%regexp_internal_match(/[^A-Za-z]/, currency));
} }
...@@ -2029,18 +2029,11 @@ function LocaleConvertCase(s, locales, isToUpper) { ...@@ -2029,18 +2029,11 @@ function LocaleConvertCase(s, locales, isToUpper) {
// StringSplit is slower than this. // StringSplit is slower than this.
var pos = %StringIndexOf(language, '-', 0); var pos = %StringIndexOf(language, '-', 0);
if (pos != -1) { if (pos !== -1) {
language = %_Call(StringSubstring, language, 0, pos); language = %_Call(StringSubstring, language, 0, pos);
} }
var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr']; return %StringLocaleConvertCase(s, isToUpper, language);
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]);
} }
/** /**
......
...@@ -1010,21 +1010,14 @@ inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) { ...@@ -1010,21 +1010,14 @@ inline int FindFirstUpperOrNonAscii(Handle<String> s, int length) {
return length; return length;
} }
} // namespace MUST_USE_RESULT Object* ConvertToLower(Handle<String> s, Isolate* isolate) {
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);
if (!s->HasOnlyOneByteChars()) { if (!s->HasOnlyOneByteChars()) {
// Use a slower implementation for strings with characters beyond U+00FF. // Use a slower implementation for strings with characters beyond U+00FF.
return LocaleConvertCase(s, isolate, false, ""); return LocaleConvertCase(s, isolate, false, "");
} }
int length = s->length();
// We depend here on the invariant that the length of a Latin1 // We depend here on the invariant that the length of a Latin1
// string is invariant under ToLowerCase, and the result always // string is invariant under ToLowerCase, and the result always
// fits in the Latin1 range in the *root locale*. It does not hold // fits in the Latin1 range in the *root locale*. It does not hold
...@@ -1080,14 +1073,8 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) { ...@@ -1080,14 +1073,8 @@ RUNTIME_FUNCTION(Runtime_StringToLowerCaseI18N) {
return *result; return *result;
} }
RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) { MUST_USE_RESULT Object* ConvertToUpper(Handle<String> s, Isolate* isolate) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
int32_t length = s->length(); int32_t length = s->length();
s = String::Flatten(s);
if (s->HasOnlyOneByteChars() && length > 0) { if (s->HasOnlyOneByteChars() && length > 0) {
Handle<SeqOneByteString> result = Handle<SeqOneByteString> result =
isolate->factory()->NewRawOneByteString(length).ToHandleChecked(); isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
...@@ -1147,26 +1134,65 @@ RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) { ...@@ -1147,26 +1134,65 @@ RUNTIME_FUNCTION(Runtime_StringToUpperCaseI18N) {
return LocaleConvertCase(s, isolate, true, ""); 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) { RUNTIME_FUNCTION(Runtime_StringLocaleConvertCase) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(args.length(), 3); DCHECK_EQ(args.length(), 3);
CONVERT_ARG_HANDLE_CHECKED(String, s, 0); CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1); CONVERT_BOOLEAN_ARG_CHECKED(is_upper, 1);
CONVERT_ARG_HANDLE_CHECKED(SeqOneByteString, lang, 2); CONVERT_ARG_HANDLE_CHECKED(String, lang_arg, 2);
// All the languages requiring special handling ("az", "el", "lt", "tr") DCHECK(lang_arg->length() <= 3);
// have a 2-letter language code. lang_arg = String::Flatten(lang_arg);
DCHECK(lang->length() == 2);
uint8_t lang_str[3]; // All the languages requiring special-handling have two-letter codes.
memcpy(lang_str, lang->GetChars(), 2); if (V8_UNLIKELY(lang_arg->length() > 2))
lang_str[2] = 0; 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); s = String::Flatten(s);
// TODO(jshin): Consider adding a fast path for ASCII or Latin-1. The fastpath // 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 // 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. // mapping of ASCII range characters are different in those locales.
// Greek (el) does not require any adjustment, though. // Greek (el) does not require any adjustment.
return LocaleConvertCase(s, isolate, is_upper, if (V8_UNLIKELY(c1 == 't' && c2 == 'r'))
reinterpret_cast<const char*>(lang_str)); 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) { 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