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 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1745 // Forward declarations. | 1745 // Forward declarations. |
1746 const int kStringBuilderConcatHelperLengthBits = 11; | 1746 const int kStringBuilderConcatHelperLengthBits = 11; |
1747 const int kStringBuilderConcatHelperPositionBits = 19; | 1747 const int kStringBuilderConcatHelperPositionBits = 19; |
1748 | 1748 |
1749 template <typename schar> | 1749 template <typename schar> |
1750 static inline void StringBuilderConcatHelper(String*, | 1750 static inline void StringBuilderConcatHelper(String*, |
1751 schar*, | 1751 schar*, |
1752 FixedArray*, | 1752 FixedArray*, |
1753 int); | 1753 int); |
1754 | 1754 |
| 1755 STATIC_ASSERT(kStringBuilderConcatHelperLengthBits + |
| 1756 kStringBuilderConcatHelperPositionBits <= kSmiValueSize); |
1755 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> | 1757 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> |
1756 StringBuilderSubstringLength; | 1758 StringBuilderSubstringLength; |
1757 typedef BitField<int, | 1759 typedef BitField<int, |
1758 kStringBuilderConcatHelperLengthBits, | 1760 kStringBuilderConcatHelperLengthBits, |
1759 kStringBuilderConcatHelperPositionBits> | 1761 kStringBuilderConcatHelperPositionBits> |
1760 StringBuilderSubstringPosition; | 1762 StringBuilderSubstringPosition; |
1761 | 1763 |
1762 | 1764 |
1763 class ReplacementStringBuilder { | 1765 class ReplacementStringBuilder { |
1764 public: | 1766 public: |
(...skipping 26 matching lines...) Expand all Loading... |
1791 } | 1793 } |
1792 | 1794 |
1793 | 1795 |
1794 void EnsureCapacity(int elements) { | 1796 void EnsureCapacity(int elements) { |
1795 array_builder_.EnsureCapacity(elements); | 1797 array_builder_.EnsureCapacity(elements); |
1796 } | 1798 } |
1797 | 1799 |
1798 | 1800 |
1799 void AddSubjectSlice(int from, int to) { | 1801 void AddSubjectSlice(int from, int to) { |
1800 AddSubjectSlice(&array_builder_, from, to); | 1802 AddSubjectSlice(&array_builder_, from, to); |
1801 // Can we encode the slice in 11 bits for length and 19 bits for | |
1802 // start position - as used by StringBuilderConcatHelper? | |
1803 IncrementCharacterCount(to - from); | 1803 IncrementCharacterCount(to - from); |
1804 } | 1804 } |
1805 | 1805 |
1806 | 1806 |
1807 void AddString(Handle<String> string) { | 1807 void AddString(Handle<String> string) { |
1808 int length = string->length(); | 1808 int length = string->length(); |
1809 ASSERT(length > 0); | 1809 ASSERT(length > 0); |
1810 AddElement(*string); | 1810 AddElement(*string); |
1811 if (!string->IsAsciiRepresentation()) { | 1811 if (!string->IsAsciiRepresentation()) { |
1812 is_ascii_ = false; | 1812 is_ascii_ = false; |
(...skipping 3607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5420 static Object* Runtime_StringAdd(Arguments args) { | 5420 static Object* Runtime_StringAdd(Arguments args) { |
5421 NoHandleAllocation ha; | 5421 NoHandleAllocation ha; |
5422 ASSERT(args.length() == 2); | 5422 ASSERT(args.length() == 2); |
5423 CONVERT_CHECKED(String, str1, args[0]); | 5423 CONVERT_CHECKED(String, str1, args[0]); |
5424 CONVERT_CHECKED(String, str2, args[1]); | 5424 CONVERT_CHECKED(String, str2, args[1]); |
5425 Counters::string_add_runtime.Increment(); | 5425 Counters::string_add_runtime.Increment(); |
5426 return Heap::AllocateConsString(str1, str2); | 5426 return Heap::AllocateConsString(str1, str2); |
5427 } | 5427 } |
5428 | 5428 |
5429 | 5429 |
5430 template<typename sinkchar> | 5430 template <typename sinkchar> |
5431 static inline void StringBuilderConcatHelper(String* special, | 5431 static inline void StringBuilderConcatHelper(String* special, |
5432 sinkchar* sink, | 5432 sinkchar* sink, |
5433 FixedArray* fixed_array, | 5433 FixedArray* fixed_array, |
5434 int array_length) { | 5434 int array_length) { |
5435 int position = 0; | 5435 int position = 0; |
5436 for (int i = 0; i < array_length; i++) { | 5436 for (int i = 0; i < array_length; i++) { |
5437 Object* element = fixed_array->get(i); | 5437 Object* element = fixed_array->get(i); |
5438 if (element->IsSmi()) { | 5438 if (element->IsSmi()) { |
5439 // Smi encoding of position and length. | 5439 // Smi encoding of position and length. |
5440 int encoded_slice = Smi::cast(element)->value(); | 5440 int encoded_slice = Smi::cast(element)->value(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5491 | 5491 |
5492 if (array_length == 0) { | 5492 if (array_length == 0) { |
5493 return Heap::empty_string(); | 5493 return Heap::empty_string(); |
5494 } else if (array_length == 1) { | 5494 } else if (array_length == 1) { |
5495 Object* first = fixed_array->get(0); | 5495 Object* first = fixed_array->get(0); |
5496 if (first->IsString()) return first; | 5496 if (first->IsString()) return first; |
5497 } | 5497 } |
5498 | 5498 |
5499 bool ascii = special->IsAsciiRepresentation(); | 5499 bool ascii = special->IsAsciiRepresentation(); |
5500 int position = 0; | 5500 int position = 0; |
5501 int increment = 0; | |
5502 for (int i = 0; i < array_length; i++) { | 5501 for (int i = 0; i < array_length; i++) { |
| 5502 int increment = 0; |
5503 Object* elt = fixed_array->get(i); | 5503 Object* elt = fixed_array->get(i); |
5504 if (elt->IsSmi()) { | 5504 if (elt->IsSmi()) { |
5505 // Smi encoding of position and length. | 5505 // Smi encoding of position and length. |
5506 int len = Smi::cast(elt)->value(); | 5506 int smi_value = Smi::cast(elt)->value(); |
5507 if (len > 0) { | 5507 int pos; |
| 5508 int len; |
| 5509 if (smi_value > 0) { |
5508 // Position and length encoded in one smi. | 5510 // Position and length encoded in one smi. |
5509 int pos = len >> 11; | 5511 pos = StringBuilderSubstringPosition::decode(smi_value); |
5510 len &= 0x7ff; | 5512 len = StringBuilderSubstringLength::decode(smi_value); |
5511 if (pos + len > special_length) { | |
5512 return Top::Throw(Heap::illegal_argument_symbol()); | |
5513 } | |
5514 increment = len; | |
5515 } else { | 5513 } else { |
5516 // Position and length encoded in two smis. | 5514 // Position and length encoded in two smis. |
5517 increment = (-len); | 5515 len = -smi_value; |
5518 // Get the position and check that it is also a smi. | 5516 // Get the position and check that it is a positive smi. |
5519 i++; | 5517 i++; |
5520 if (i >= array_length) { | 5518 if (i >= array_length) { |
5521 return Top::Throw(Heap::illegal_argument_symbol()); | 5519 return Top::Throw(Heap::illegal_argument_symbol()); |
5522 } | 5520 } |
5523 Object* pos = fixed_array->get(i); | 5521 Object* next_smi = fixed_array->get(i); |
5524 if (!pos->IsSmi()) { | 5522 if (!next_smi->IsSmi()) { |
| 5523 return Top::Throw(Heap::illegal_argument_symbol()); |
| 5524 } |
| 5525 pos = Smi::cast(next_smi)->value(); |
| 5526 if (pos < 0) { |
5525 return Top::Throw(Heap::illegal_argument_symbol()); | 5527 return Top::Throw(Heap::illegal_argument_symbol()); |
5526 } | 5528 } |
5527 } | 5529 } |
| 5530 ASSERT(pos >= 0); |
| 5531 ASSERT(len >= 0); |
| 5532 if (pos > special_length || len > special_length - pos) { |
| 5533 return Top::Throw(Heap::illegal_argument_symbol()); |
| 5534 } |
| 5535 increment = len; |
5528 } else if (elt->IsString()) { | 5536 } else if (elt->IsString()) { |
5529 String* element = String::cast(elt); | 5537 String* element = String::cast(elt); |
5530 int element_length = element->length(); | 5538 int element_length = element->length(); |
5531 increment = element_length; | 5539 increment = element_length; |
5532 if (ascii && !element->IsAsciiRepresentation()) { | 5540 if (ascii && !element->IsAsciiRepresentation()) { |
5533 ascii = false; | 5541 ascii = false; |
5534 } | 5542 } |
5535 } else { | 5543 } else { |
5536 return Top::Throw(Heap::illegal_argument_symbol()); | 5544 return Top::Throw(Heap::illegal_argument_symbol()); |
5537 } | 5545 } |
(...skipping 4655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10193 } else { | 10201 } else { |
10194 // Handle last resort GC and make sure to allow future allocations | 10202 // Handle last resort GC and make sure to allow future allocations |
10195 // to grow the heap without causing GCs (if possible). | 10203 // to grow the heap without causing GCs (if possible). |
10196 Counters::gc_last_resort_from_js.Increment(); | 10204 Counters::gc_last_resort_from_js.Increment(); |
10197 Heap::CollectAllGarbage(false); | 10205 Heap::CollectAllGarbage(false); |
10198 } | 10206 } |
10199 } | 10207 } |
10200 | 10208 |
10201 | 10209 |
10202 } } // namespace v8::internal | 10210 } } // namespace v8::internal |
OLD | NEW |