OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 6267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6278 | 6278 |
6279 // ECMA-262 section 15.1.2.3, empty string is NaN | 6279 // ECMA-262 section 15.1.2.3, empty string is NaN |
6280 double value = StringToDouble(isolate->unicode_cache(), | 6280 double value = StringToDouble(isolate->unicode_cache(), |
6281 str, ALLOW_TRAILING_JUNK, OS::nan_value()); | 6281 str, ALLOW_TRAILING_JUNK, OS::nan_value()); |
6282 | 6282 |
6283 // Create a number object from the value. | 6283 // Create a number object from the value. |
6284 return isolate->heap()->NumberFromDouble(value); | 6284 return isolate->heap()->NumberFromDouble(value); |
6285 } | 6285 } |
6286 | 6286 |
6287 | 6287 |
| 6288 static inline bool ToUpperOverflows(uc32 character) { |
| 6289 // y with umlauts and the micro sign are the only characters that stop |
| 6290 // fitting into one-byte when converting to uppercase. |
| 6291 static const uc32 yuml_code = 0xff; |
| 6292 static const uc32 micro_code = 0xb5; |
| 6293 return (character == yuml_code || character == micro_code); |
| 6294 } |
| 6295 |
| 6296 |
6288 template <class Converter> | 6297 template <class Converter> |
6289 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( | 6298 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( |
6290 Isolate* isolate, | 6299 Isolate* isolate, |
6291 String* s, | 6300 String* s, |
6292 String::Encoding result_encoding, | 6301 String::Encoding result_encoding, |
6293 int length, | 6302 int length, |
6294 int input_string_length, | 6303 int input_string_length, |
6295 unibrow::Mapping<Converter, 128>* mapping) { | 6304 unibrow::Mapping<Converter, 128>* mapping) { |
6296 // We try this twice, once with the assumption that the result is no longer | 6305 // We try this twice, once with the assumption that the result is no longer |
6297 // than the input and, if that assumption breaks, again with the exact | 6306 // than the input and, if that assumption breaks, again with the exact |
(...skipping 18 matching lines...) Expand all Loading... |
6316 DisallowHeapAllocation no_gc; | 6325 DisallowHeapAllocation no_gc; |
6317 | 6326 |
6318 // Convert all characters to upper case, assuming that they will fit | 6327 // Convert all characters to upper case, assuming that they will fit |
6319 // in the buffer | 6328 // in the buffer |
6320 Access<ConsStringIteratorOp> op( | 6329 Access<ConsStringIteratorOp> op( |
6321 isolate->runtime_state()->string_iterator()); | 6330 isolate->runtime_state()->string_iterator()); |
6322 StringCharacterStream stream(s, op.value()); | 6331 StringCharacterStream stream(s, op.value()); |
6323 unibrow::uchar chars[Converter::kMaxWidth]; | 6332 unibrow::uchar chars[Converter::kMaxWidth]; |
6324 // We can assume that the string is not empty | 6333 // We can assume that the string is not empty |
6325 uc32 current = stream.GetNext(); | 6334 uc32 current = stream.GetNext(); |
6326 // y with umlauts is the only character that stops fitting into one-byte | 6335 bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString(); |
6327 // when converting to uppercase. | |
6328 static const uc32 yuml_code = 0xff; | |
6329 bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower; | |
6330 for (int i = 0; i < length;) { | 6336 for (int i = 0; i < length;) { |
6331 bool has_next = stream.HasMore(); | 6337 bool has_next = stream.HasMore(); |
6332 uc32 next = has_next ? stream.GetNext() : 0; | 6338 uc32 next = has_next ? stream.GetNext() : 0; |
6333 int char_length = mapping->get(current, next, chars); | 6339 int char_length = mapping->get(current, next, chars); |
6334 if (char_length == 0) { | 6340 if (char_length == 0) { |
6335 // The case conversion of this character is the character itself. | 6341 // The case conversion of this character is the character itself. |
6336 result->Set(i, current); | 6342 result->Set(i, current); |
6337 i++; | 6343 i++; |
6338 } else if (char_length == 1 && (ignore_yuml || current != yuml_code)) { | 6344 } else if (char_length == 1 && |
| 6345 (ignore_overflow || !ToUpperOverflows(current))) { |
6339 // Common case: converting the letter resulted in one character. | 6346 // Common case: converting the letter resulted in one character. |
6340 ASSERT(static_cast<uc32>(chars[0]) != current); | 6347 ASSERT(static_cast<uc32>(chars[0]) != current); |
6341 result->Set(i, chars[0]); | 6348 result->Set(i, chars[0]); |
6342 has_changed_character = true; | 6349 has_changed_character = true; |
6343 i++; | 6350 i++; |
6344 } else if (length == input_string_length) { | 6351 } else if (length == input_string_length) { |
6345 bool found_yuml = (current == yuml_code); | 6352 bool overflows = ToUpperOverflows(current); |
6346 // We've assumed that the result would be as long as the | 6353 // We've assumed that the result would be as long as the |
6347 // input but here is a character that converts to several | 6354 // input but here is a character that converts to several |
6348 // characters. No matter, we calculate the exact length | 6355 // characters. No matter, we calculate the exact length |
6349 // of the result and try the whole thing again. | 6356 // of the result and try the whole thing again. |
6350 // | 6357 // |
6351 // Note that this leaves room for optimization. We could just | 6358 // Note that this leaves room for optimization. We could just |
6352 // memcpy what we already have to the result string. Also, | 6359 // memcpy what we already have to the result string. Also, |
6353 // the result string is the last object allocated we could | 6360 // the result string is the last object allocated we could |
6354 // "realloc" it and probably, in the vast majority of cases, | 6361 // "realloc" it and probably, in the vast majority of cases, |
6355 // extend the existing string to be able to hold the full | 6362 // extend the existing string to be able to hold the full |
6356 // result. | 6363 // result. |
6357 int next_length = 0; | 6364 int next_length = 0; |
6358 if (has_next) { | 6365 if (has_next) { |
6359 next_length = mapping->get(next, 0, chars); | 6366 next_length = mapping->get(next, 0, chars); |
6360 if (next_length == 0) next_length = 1; | 6367 if (next_length == 0) next_length = 1; |
6361 } | 6368 } |
6362 int current_length = i + char_length + next_length; | 6369 int current_length = i + char_length + next_length; |
6363 while (stream.HasMore()) { | 6370 while (stream.HasMore()) { |
6364 current = stream.GetNext(); | 6371 current = stream.GetNext(); |
6365 found_yuml |= (current == yuml_code); | 6372 overflows |= ToUpperOverflows(current); |
6366 // NOTE: we use 0 as the next character here because, while | 6373 // NOTE: we use 0 as the next character here because, while |
6367 // the next character may affect what a character converts to, | 6374 // the next character may affect what a character converts to, |
6368 // it does not in any case affect the length of what it convert | 6375 // it does not in any case affect the length of what it convert |
6369 // to. | 6376 // to. |
6370 int char_length = mapping->get(current, 0, chars); | 6377 int char_length = mapping->get(current, 0, chars); |
6371 if (char_length == 0) char_length = 1; | 6378 if (char_length == 0) char_length = 1; |
6372 current_length += char_length; | 6379 current_length += char_length; |
6373 if (current_length > Smi::kMaxValue) { | 6380 if (current_length > Smi::kMaxValue) { |
6374 isolate->context()->mark_out_of_memory(); | 6381 isolate->context()->mark_out_of_memory(); |
6375 return Failure::OutOfMemoryException(0x13); | 6382 return Failure::OutOfMemoryException(0x13); |
6376 } | 6383 } |
6377 } | 6384 } |
6378 // Try again with the real length. Return signed if we need | 6385 // Try again with the real length. Return signed if we need |
6379 // to allocate a two-byte string for y-umlaut to uppercase. | 6386 // to allocate a two-byte string for to uppercase. |
6380 return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length) | 6387 return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length) |
6381 : Smi::FromInt(current_length); | 6388 : Smi::FromInt(current_length); |
6382 } else { | 6389 } else { |
6383 for (int j = 0; j < char_length; j++) { | 6390 for (int j = 0; j < char_length; j++) { |
6384 result->Set(i, chars[j]); | 6391 result->Set(i, chars[j]); |
6385 i++; | 6392 i++; |
6386 } | 6393 } |
6387 has_changed_character = true; | 6394 has_changed_character = true; |
6388 } | 6395 } |
6389 current = next; | 6396 current = next; |
6390 } | 6397 } |
6391 if (has_changed_character) { | 6398 if (has_changed_character) { |
(...skipping 8523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14915 // Handle last resort GC and make sure to allow future allocations | 14922 // Handle last resort GC and make sure to allow future allocations |
14916 // to grow the heap without causing GCs (if possible). | 14923 // to grow the heap without causing GCs (if possible). |
14917 isolate->counters()->gc_last_resort_from_js()->Increment(); | 14924 isolate->counters()->gc_last_resort_from_js()->Increment(); |
14918 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 14925 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
14919 "Runtime::PerformGC"); | 14926 "Runtime::PerformGC"); |
14920 } | 14927 } |
14921 } | 14928 } |
14922 | 14929 |
14923 | 14930 |
14924 } } // namespace v8::internal | 14931 } } // namespace v8::internal |
OLD | NEW |