OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 4909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4920 } else { | 4920 } else { |
4921 // If we didn't actually change anything in doing the conversion | 4921 // If we didn't actually change anything in doing the conversion |
4922 // we simple return the result and let the converted string | 4922 // we simple return the result and let the converted string |
4923 // become garbage; there is no reason to keep two identical strings | 4923 // become garbage; there is no reason to keep two identical strings |
4924 // alive. | 4924 // alive. |
4925 return s; | 4925 return s; |
4926 } | 4926 } |
4927 } | 4927 } |
4928 | 4928 |
4929 | 4929 |
4930 static inline SeqAsciiString* TryGetSeqAsciiString(String* s) { | |
4931 if (!s->IsFlat() || !s->IsAsciiRepresentation()) return NULL; | |
4932 if (s->IsConsString()) { | |
4933 ASSERT(ConsString::cast(s)->second()->length() == 0); | |
4934 return SeqAsciiString::cast(ConsString::cast(s)->first()); | |
4935 } | |
4936 return SeqAsciiString::cast(s); | |
4937 } | |
4938 | |
4939 | |
4940 namespace { | 4930 namespace { |
4941 | 4931 |
4942 struct ToLowerTraits { | 4932 struct ToLowerTraits { |
4943 typedef unibrow::ToLowercase UnibrowConverter; | 4933 typedef unibrow::ToLowercase UnibrowConverter; |
4944 | 4934 |
4945 static bool ConvertAscii(char* dst, char* src, int length) { | 4935 static bool ConvertAscii(char* dst, char* src, int length) { |
4946 bool changed = false; | 4936 bool changed = false; |
4947 for (int i = 0; i < length; ++i) { | 4937 for (int i = 0; i < length; ++i) { |
4948 char c = src[i]; | 4938 char c = src[i]; |
4949 if ('A' <= c && c <= 'Z') { | 4939 if ('A' <= c && c <= 'Z') { |
(...skipping 26 matching lines...) Expand all Loading... |
4976 | 4966 |
4977 } // namespace | 4967 } // namespace |
4978 | 4968 |
4979 | 4969 |
4980 template <typename ConvertTraits> | 4970 template <typename ConvertTraits> |
4981 static Object* ConvertCase( | 4971 static Object* ConvertCase( |
4982 Arguments args, | 4972 Arguments args, |
4983 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { | 4973 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { |
4984 NoHandleAllocation ha; | 4974 NoHandleAllocation ha; |
4985 CONVERT_CHECKED(String, s, args[0]); | 4975 CONVERT_CHECKED(String, s, args[0]); |
4986 s->TryFlatten(); | 4976 s = s->TryFlattenGetString(); |
4987 | 4977 |
4988 const int length = s->length(); | 4978 const int length = s->length(); |
4989 // Assume that the string is not empty; we need this assumption later | 4979 // Assume that the string is not empty; we need this assumption later |
4990 if (length == 0) return s; | 4980 if (length == 0) return s; |
4991 | 4981 |
4992 // Simpler handling of ascii strings. | 4982 // Simpler handling of ascii strings. |
4993 // | 4983 // |
4994 // NOTE: This assumes that the upper/lower case of an ascii | 4984 // NOTE: This assumes that the upper/lower case of an ascii |
4995 // character is also ascii. This is currently the case, but it | 4985 // character is also ascii. This is currently the case, but it |
4996 // might break in the future if we implement more context and locale | 4986 // might break in the future if we implement more context and locale |
4997 // dependent upper/lower conversions. | 4987 // dependent upper/lower conversions. |
4998 SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s); | 4988 if (s->IsSeqAsciiString()) { |
4999 if (seq_ascii != NULL) { | |
5000 Object* o = Heap::AllocateRawAsciiString(length); | 4989 Object* o = Heap::AllocateRawAsciiString(length); |
5001 if (o->IsFailure()) return o; | 4990 if (o->IsFailure()) return o; |
5002 SeqAsciiString* result = SeqAsciiString::cast(o); | 4991 SeqAsciiString* result = SeqAsciiString::cast(o); |
5003 bool has_changed_character = ConvertTraits::ConvertAscii( | 4992 bool has_changed_character = ConvertTraits::ConvertAscii( |
5004 result->GetChars(), seq_ascii->GetChars(), length); | 4993 result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length); |
5005 return has_changed_character ? result : s; | 4994 return has_changed_character ? result : s; |
5006 } | 4995 } |
5007 | 4996 |
5008 Object* answer = ConvertCaseHelper(s, length, length, mapping); | 4997 Object* answer = ConvertCaseHelper(s, length, length, mapping); |
5009 if (answer->IsSmi()) { | 4998 if (answer->IsSmi()) { |
5010 // Retry with correct length. | 4999 // Retry with correct length. |
5011 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); | 5000 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); |
5012 } | 5001 } |
5013 return answer; // This may be a failure. | 5002 return answer; // This may be a failure. |
5014 } | 5003 } |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5538 array_length = fixed_array->length(); | 5527 array_length = fixed_array->length(); |
5539 } | 5528 } |
5540 | 5529 |
5541 if (array_length == 0) { | 5530 if (array_length == 0) { |
5542 return Heap::empty_string(); | 5531 return Heap::empty_string(); |
5543 } else if (array_length == 1) { | 5532 } else if (array_length == 1) { |
5544 Object* first = fixed_array->get(0); | 5533 Object* first = fixed_array->get(0); |
5545 if (first->IsString()) return first; | 5534 if (first->IsString()) return first; |
5546 } | 5535 } |
5547 | 5536 |
5548 bool ascii = special->IsAsciiRepresentation(); | 5537 bool ascii = special->HasAsciiChars(); |
5549 int position = 0; | 5538 int position = 0; |
5550 for (int i = 0; i < array_length; i++) { | 5539 for (int i = 0; i < array_length; i++) { |
5551 int increment = 0; | 5540 int increment = 0; |
5552 Object* elt = fixed_array->get(i); | 5541 Object* elt = fixed_array->get(i); |
5553 if (elt->IsSmi()) { | 5542 if (elt->IsSmi()) { |
5554 // Smi encoding of position and length. | 5543 // Smi encoding of position and length. |
5555 int smi_value = Smi::cast(elt)->value(); | 5544 int smi_value = Smi::cast(elt)->value(); |
5556 int pos; | 5545 int pos; |
5557 int len; | 5546 int len; |
5558 if (smi_value > 0) { | 5547 if (smi_value > 0) { |
(...skipping 20 matching lines...) Expand all Loading... |
5579 ASSERT(pos >= 0); | 5568 ASSERT(pos >= 0); |
5580 ASSERT(len >= 0); | 5569 ASSERT(len >= 0); |
5581 if (pos > special_length || len > special_length - pos) { | 5570 if (pos > special_length || len > special_length - pos) { |
5582 return Top::Throw(Heap::illegal_argument_symbol()); | 5571 return Top::Throw(Heap::illegal_argument_symbol()); |
5583 } | 5572 } |
5584 increment = len; | 5573 increment = len; |
5585 } else if (elt->IsString()) { | 5574 } else if (elt->IsString()) { |
5586 String* element = String::cast(elt); | 5575 String* element = String::cast(elt); |
5587 int element_length = element->length(); | 5576 int element_length = element->length(); |
5588 increment = element_length; | 5577 increment = element_length; |
5589 if (ascii && !element->IsAsciiRepresentation()) { | 5578 if (ascii && !element->HasAsciiChars()) { |
5590 ascii = false; | 5579 ascii = false; |
5591 } | 5580 } |
5592 } else { | 5581 } else { |
5593 return Top::Throw(Heap::illegal_argument_symbol()); | 5582 return Top::Throw(Heap::illegal_argument_symbol()); |
5594 } | 5583 } |
5595 if (increment > String::kMaxLength - position) { | 5584 if (increment > String::kMaxLength - position) { |
5596 Top::context()->mark_out_of_memory(); | 5585 Top::context()->mark_out_of_memory(); |
5597 return Failure::OutOfMemoryException(); | 5586 return Failure::OutOfMemoryException(); |
5598 } | 5587 } |
5599 position += increment; | 5588 position += increment; |
(...skipping 4772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10372 } else { | 10361 } else { |
10373 // Handle last resort GC and make sure to allow future allocations | 10362 // Handle last resort GC and make sure to allow future allocations |
10374 // to grow the heap without causing GCs (if possible). | 10363 // to grow the heap without causing GCs (if possible). |
10375 Counters::gc_last_resort_from_js.Increment(); | 10364 Counters::gc_last_resort_from_js.Increment(); |
10376 Heap::CollectAllGarbage(false); | 10365 Heap::CollectAllGarbage(false); |
10377 } | 10366 } |
10378 } | 10367 } |
10379 | 10368 |
10380 | 10369 |
10381 } } // namespace v8::internal | 10370 } } // namespace v8::internal |
OLD | NEW |