| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 422da34e7fe1616b8806b7958e15eb2dc1174b74..0d7a38258e3bf88157e7b1b73d45127d9d530d0d 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -6285,6 +6285,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
|
| }
|
|
|
|
|
| +static inline bool ToUpperOverflows(uc32 character) {
|
| + // y with umlauts and the micro sign are the only characters that stop
|
| + // fitting into one-byte when converting to uppercase.
|
| + static const uc32 yuml_code = 0xff;
|
| + static const uc32 micro_code = 0xb5;
|
| + return (character == yuml_code || character == micro_code);
|
| +}
|
| +
|
| +
|
| template <class Converter>
|
| MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
| Isolate* isolate,
|
| @@ -6323,10 +6332,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
| unibrow::uchar chars[Converter::kMaxWidth];
|
| // We can assume that the string is not empty
|
| uc32 current = stream.GetNext();
|
| - // y with umlauts is the only character that stops fitting into one-byte
|
| - // when converting to uppercase.
|
| - static const uc32 yuml_code = 0xff;
|
| - bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower;
|
| + bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
|
| for (int i = 0; i < length;) {
|
| bool has_next = stream.HasMore();
|
| uc32 next = has_next ? stream.GetNext() : 0;
|
| @@ -6335,14 +6341,15 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
| // The case conversion of this character is the character itself.
|
| result->Set(i, current);
|
| i++;
|
| - } else if (char_length == 1 && (ignore_yuml || current != yuml_code)) {
|
| + } else if (char_length == 1 &&
|
| + (ignore_overflow || !ToUpperOverflows(current))) {
|
| // Common case: converting the letter resulted in one character.
|
| ASSERT(static_cast<uc32>(chars[0]) != current);
|
| result->Set(i, chars[0]);
|
| has_changed_character = true;
|
| i++;
|
| } else if (length == input_string_length) {
|
| - bool found_yuml = (current == yuml_code);
|
| + bool overflows = ToUpperOverflows(current);
|
| // We've assumed that the result would be as long as the
|
| // input but here is a character that converts to several
|
| // characters. No matter, we calculate the exact length
|
| @@ -6362,7 +6369,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
| int current_length = i + char_length + next_length;
|
| while (stream.HasMore()) {
|
| current = stream.GetNext();
|
| - found_yuml |= (current == yuml_code);
|
| + overflows |= ToUpperOverflows(current);
|
| // NOTE: we use 0 as the next character here because, while
|
| // the next character may affect what a character converts to,
|
| // it does not in any case affect the length of what it convert
|
| @@ -6376,9 +6383,9 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
|
| }
|
| }
|
| // Try again with the real length. Return signed if we need
|
| - // to allocate a two-byte string for y-umlaut to uppercase.
|
| - return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length)
|
| - : Smi::FromInt(current_length);
|
| + // to allocate a two-byte string for to uppercase.
|
| + return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
|
| + : Smi::FromInt(current_length);
|
| } else {
|
| for (int j = 0; j < char_length; j++) {
|
| result->Set(i, chars[j]);
|
|
|