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 3345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3356 } | 3356 } |
3357 | 3357 |
3358 bool first_is_ascii = first->IsOneByteRepresentation(); | 3358 bool first_is_ascii = first->IsOneByteRepresentation(); |
3359 bool second_is_ascii = second->IsOneByteRepresentation(); | 3359 bool second_is_ascii = second->IsOneByteRepresentation(); |
3360 bool is_ascii = first_is_ascii && second_is_ascii; | 3360 bool is_ascii = first_is_ascii && second_is_ascii; |
3361 | 3361 |
3362 // Make sure that an out of memory exception is thrown if the length | 3362 // Make sure that an out of memory exception is thrown if the length |
3363 // of the new cons string is too large. | 3363 // of the new cons string is too large. |
3364 if (length > String::kMaxLength || length < 0) { | 3364 if (length > String::kMaxLength || length < 0) { |
3365 isolate()->context()->mark_out_of_memory(); | 3365 isolate()->context()->mark_out_of_memory(); |
3366 return Failure::OutOfMemoryException(); | 3366 return Failure::OutOfMemoryException(0x4); |
3367 } | 3367 } |
3368 | 3368 |
3369 bool is_ascii_data_in_two_byte_string = false; | 3369 bool is_ascii_data_in_two_byte_string = false; |
3370 if (!is_ascii) { | 3370 if (!is_ascii) { |
3371 // At least one of the strings uses two-byte representation so we | 3371 // At least one of the strings uses two-byte representation so we |
3372 // can't use the fast case code for short ASCII strings below, but | 3372 // can't use the fast case code for short ASCII strings below, but |
3373 // we can try to save memory if all chars actually fit in ASCII. | 3373 // we can try to save memory if all chars actually fit in ASCII. |
3374 is_ascii_data_in_two_byte_string = | 3374 is_ascii_data_in_two_byte_string = |
3375 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); | 3375 first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars(); |
3376 if (is_ascii_data_in_two_byte_string) { | 3376 if (is_ascii_data_in_two_byte_string) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3544 sliced_string->parent()->IsExternalString()); | 3544 sliced_string->parent()->IsExternalString()); |
3545 return result; | 3545 return result; |
3546 } | 3546 } |
3547 | 3547 |
3548 | 3548 |
3549 MaybeObject* Heap::AllocateExternalStringFromAscii( | 3549 MaybeObject* Heap::AllocateExternalStringFromAscii( |
3550 const ExternalAsciiString::Resource* resource) { | 3550 const ExternalAsciiString::Resource* resource) { |
3551 size_t length = resource->length(); | 3551 size_t length = resource->length(); |
3552 if (length > static_cast<size_t>(String::kMaxLength)) { | 3552 if (length > static_cast<size_t>(String::kMaxLength)) { |
3553 isolate()->context()->mark_out_of_memory(); | 3553 isolate()->context()->mark_out_of_memory(); |
3554 return Failure::OutOfMemoryException(); | 3554 return Failure::OutOfMemoryException(0x5); |
3555 } | 3555 } |
3556 | 3556 |
3557 ASSERT(String::IsAscii(resource->data(), static_cast<int>(length))); | 3557 ASSERT(String::IsAscii(resource->data(), static_cast<int>(length))); |
3558 | 3558 |
3559 Map* map = external_ascii_string_map(); | 3559 Map* map = external_ascii_string_map(); |
3560 Object* result; | 3560 Object* result; |
3561 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); | 3561 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
3562 if (!maybe_result->ToObject(&result)) return maybe_result; | 3562 if (!maybe_result->ToObject(&result)) return maybe_result; |
3563 } | 3563 } |
3564 | 3564 |
3565 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); | 3565 ExternalAsciiString* external_string = ExternalAsciiString::cast(result); |
3566 external_string->set_length(static_cast<int>(length)); | 3566 external_string->set_length(static_cast<int>(length)); |
3567 external_string->set_hash_field(String::kEmptyHashField); | 3567 external_string->set_hash_field(String::kEmptyHashField); |
3568 external_string->set_resource(resource); | 3568 external_string->set_resource(resource); |
3569 | 3569 |
3570 return result; | 3570 return result; |
3571 } | 3571 } |
3572 | 3572 |
3573 | 3573 |
3574 MaybeObject* Heap::AllocateExternalStringFromTwoByte( | 3574 MaybeObject* Heap::AllocateExternalStringFromTwoByte( |
3575 const ExternalTwoByteString::Resource* resource) { | 3575 const ExternalTwoByteString::Resource* resource) { |
3576 size_t length = resource->length(); | 3576 size_t length = resource->length(); |
3577 if (length > static_cast<size_t>(String::kMaxLength)) { | 3577 if (length > static_cast<size_t>(String::kMaxLength)) { |
3578 isolate()->context()->mark_out_of_memory(); | 3578 isolate()->context()->mark_out_of_memory(); |
3579 return Failure::OutOfMemoryException(); | 3579 return Failure::OutOfMemoryException(0x6); |
3580 } | 3580 } |
3581 | 3581 |
3582 // For small strings we check whether the resource contains only | 3582 // For small strings we check whether the resource contains only |
3583 // ASCII characters. If yes, we use a different string map. | 3583 // ASCII characters. If yes, we use a different string map. |
3584 static const size_t kAsciiCheckLengthLimit = 32; | 3584 static const size_t kAsciiCheckLengthLimit = 32; |
3585 bool is_ascii = length <= kAsciiCheckLengthLimit && | 3585 bool is_ascii = length <= kAsciiCheckLengthLimit && |
3586 String::IsAscii(resource->data(), static_cast<int>(length)); | 3586 String::IsAscii(resource->data(), static_cast<int>(length)); |
3587 Map* map = is_ascii ? | 3587 Map* map = is_ascii ? |
3588 external_string_with_ascii_data_map() : external_string_map(); | 3588 external_string_with_ascii_data_map() : external_string_map(); |
3589 Object* result; | 3589 Object* result; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3621 if (!maybe_result->ToObject(&result)) return maybe_result; | 3621 if (!maybe_result->ToObject(&result)) return maybe_result; |
3622 } | 3622 } |
3623 String* answer = String::cast(result); | 3623 String* answer = String::cast(result); |
3624 answer->Set(0, code); | 3624 answer->Set(0, code); |
3625 return answer; | 3625 return answer; |
3626 } | 3626 } |
3627 | 3627 |
3628 | 3628 |
3629 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { | 3629 MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { |
3630 if (length < 0 || length > ByteArray::kMaxLength) { | 3630 if (length < 0 || length > ByteArray::kMaxLength) { |
3631 return Failure::OutOfMemoryException(); | 3631 return Failure::OutOfMemoryException(0x7); |
3632 } | 3632 } |
3633 if (pretenure == NOT_TENURED) { | 3633 if (pretenure == NOT_TENURED) { |
3634 return AllocateByteArray(length); | 3634 return AllocateByteArray(length); |
3635 } | 3635 } |
3636 int size = ByteArray::SizeFor(length); | 3636 int size = ByteArray::SizeFor(length); |
3637 Object* result; | 3637 Object* result; |
3638 { MaybeObject* maybe_result = (size <= Page::kMaxNonCodeHeapObjectSize) | 3638 { MaybeObject* maybe_result = (size <= Page::kMaxNonCodeHeapObjectSize) |
3639 ? old_data_space_->AllocateRaw(size) | 3639 ? old_data_space_->AllocateRaw(size) |
3640 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); | 3640 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); |
3641 if (!maybe_result->ToObject(&result)) return maybe_result; | 3641 if (!maybe_result->ToObject(&result)) return maybe_result; |
3642 } | 3642 } |
3643 | 3643 |
3644 reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier( | 3644 reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier( |
3645 byte_array_map()); | 3645 byte_array_map()); |
3646 reinterpret_cast<ByteArray*>(result)->set_length(length); | 3646 reinterpret_cast<ByteArray*>(result)->set_length(length); |
3647 return result; | 3647 return result; |
3648 } | 3648 } |
3649 | 3649 |
3650 | 3650 |
3651 MaybeObject* Heap::AllocateByteArray(int length) { | 3651 MaybeObject* Heap::AllocateByteArray(int length) { |
3652 if (length < 0 || length > ByteArray::kMaxLength) { | 3652 if (length < 0 || length > ByteArray::kMaxLength) { |
3653 return Failure::OutOfMemoryException(); | 3653 return Failure::OutOfMemoryException(0x8); |
3654 } | 3654 } |
3655 int size = ByteArray::SizeFor(length); | 3655 int size = ByteArray::SizeFor(length); |
3656 AllocationSpace space = | 3656 AllocationSpace space = |
3657 (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : NEW_SPACE; | 3657 (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : NEW_SPACE; |
3658 Object* result; | 3658 Object* result; |
3659 { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE); | 3659 { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE); |
3660 if (!maybe_result->ToObject(&result)) return maybe_result; | 3660 if (!maybe_result->ToObject(&result)) return maybe_result; |
3661 } | 3661 } |
3662 | 3662 |
3663 reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier( | 3663 reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier( |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4692 int chars, | 4692 int chars, |
4693 uint32_t hash_field) { | 4693 uint32_t hash_field) { |
4694 typedef AllocateInternalSymbolHelper<T> H; | 4694 typedef AllocateInternalSymbolHelper<T> H; |
4695 ASSERT(chars >= 0); | 4695 ASSERT(chars >= 0); |
4696 // Compute map and object size. | 4696 // Compute map and object size. |
4697 int size; | 4697 int size; |
4698 Map* map; | 4698 Map* map; |
4699 | 4699 |
4700 if (is_one_byte) { | 4700 if (is_one_byte) { |
4701 if (chars > SeqOneByteString::kMaxLength) { | 4701 if (chars > SeqOneByteString::kMaxLength) { |
4702 return Failure::OutOfMemoryException(); | 4702 return Failure::OutOfMemoryException(0x9); |
4703 } | 4703 } |
4704 map = ascii_symbol_map(); | 4704 map = ascii_symbol_map(); |
4705 size = SeqOneByteString::SizeFor(chars); | 4705 size = SeqOneByteString::SizeFor(chars); |
4706 } else { | 4706 } else { |
4707 if (chars > SeqTwoByteString::kMaxLength) { | 4707 if (chars > SeqTwoByteString::kMaxLength) { |
4708 return Failure::OutOfMemoryException(); | 4708 return Failure::OutOfMemoryException(0xa); |
4709 } | 4709 } |
4710 map = symbol_map(); | 4710 map = symbol_map(); |
4711 size = SeqTwoByteString::SizeFor(chars); | 4711 size = SeqTwoByteString::SizeFor(chars); |
4712 } | 4712 } |
4713 | 4713 |
4714 // Allocate string. | 4714 // Allocate string. |
4715 Object* result; | 4715 Object* result; |
4716 { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize) | 4716 { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize) |
4717 ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE) | 4717 ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE) |
4718 : old_data_space_->AllocateRaw(size); | 4718 : old_data_space_->AllocateRaw(size); |
(...skipping 24 matching lines...) Expand all Loading... |
4743 MaybeObject* Heap::AllocateInternalSymbol<false>(String*, int, uint32_t); | 4743 MaybeObject* Heap::AllocateInternalSymbol<false>(String*, int, uint32_t); |
4744 template | 4744 template |
4745 MaybeObject* Heap::AllocateInternalSymbol<false>(Vector<const char>, | 4745 MaybeObject* Heap::AllocateInternalSymbol<false>(Vector<const char>, |
4746 int, | 4746 int, |
4747 uint32_t); | 4747 uint32_t); |
4748 | 4748 |
4749 | 4749 |
4750 MaybeObject* Heap::AllocateRawOneByteString(int length, | 4750 MaybeObject* Heap::AllocateRawOneByteString(int length, |
4751 PretenureFlag pretenure) { | 4751 PretenureFlag pretenure) { |
4752 if (length < 0 || length > SeqOneByteString::kMaxLength) { | 4752 if (length < 0 || length > SeqOneByteString::kMaxLength) { |
4753 return Failure::OutOfMemoryException(); | 4753 return Failure::OutOfMemoryException(0xb); |
4754 } | 4754 } |
4755 | 4755 |
4756 int size = SeqOneByteString::SizeFor(length); | 4756 int size = SeqOneByteString::SizeFor(length); |
4757 ASSERT(size <= SeqOneByteString::kMaxSize); | 4757 ASSERT(size <= SeqOneByteString::kMaxSize); |
4758 | 4758 |
4759 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 4759 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
4760 AllocationSpace retry_space = OLD_DATA_SPACE; | 4760 AllocationSpace retry_space = OLD_DATA_SPACE; |
4761 | 4761 |
4762 if (space == NEW_SPACE) { | 4762 if (space == NEW_SPACE) { |
4763 if (size > kMaxObjectSizeInNewSpace) { | 4763 if (size > kMaxObjectSizeInNewSpace) { |
(...skipping 27 matching lines...) Expand all Loading... |
4791 } | 4791 } |
4792 #endif | 4792 #endif |
4793 | 4793 |
4794 return result; | 4794 return result; |
4795 } | 4795 } |
4796 | 4796 |
4797 | 4797 |
4798 MaybeObject* Heap::AllocateRawTwoByteString(int length, | 4798 MaybeObject* Heap::AllocateRawTwoByteString(int length, |
4799 PretenureFlag pretenure) { | 4799 PretenureFlag pretenure) { |
4800 if (length < 0 || length > SeqTwoByteString::kMaxLength) { | 4800 if (length < 0 || length > SeqTwoByteString::kMaxLength) { |
4801 return Failure::OutOfMemoryException(); | 4801 return Failure::OutOfMemoryException(0xc); |
4802 } | 4802 } |
4803 int size = SeqTwoByteString::SizeFor(length); | 4803 int size = SeqTwoByteString::SizeFor(length); |
4804 ASSERT(size <= SeqTwoByteString::kMaxSize); | 4804 ASSERT(size <= SeqTwoByteString::kMaxSize); |
4805 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 4805 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
4806 AllocationSpace retry_space = OLD_DATA_SPACE; | 4806 AllocationSpace retry_space = OLD_DATA_SPACE; |
4807 | 4807 |
4808 if (space == NEW_SPACE) { | 4808 if (space == NEW_SPACE) { |
4809 if (size > kMaxObjectSizeInNewSpace) { | 4809 if (size > kMaxObjectSizeInNewSpace) { |
4810 // Allocate in large object space, retry space will be ignored. | 4810 // Allocate in large object space, retry space will be ignored. |
4811 space = LO_SPACE; | 4811 space = LO_SPACE; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4860 // Initialize the object. | 4860 // Initialize the object. |
4861 reinterpret_cast<FixedArray*>(result)->set_map_no_write_barrier( | 4861 reinterpret_cast<FixedArray*>(result)->set_map_no_write_barrier( |
4862 fixed_array_map()); | 4862 fixed_array_map()); |
4863 reinterpret_cast<FixedArray*>(result)->set_length(0); | 4863 reinterpret_cast<FixedArray*>(result)->set_length(0); |
4864 return result; | 4864 return result; |
4865 } | 4865 } |
4866 | 4866 |
4867 | 4867 |
4868 MaybeObject* Heap::AllocateRawFixedArray(int length) { | 4868 MaybeObject* Heap::AllocateRawFixedArray(int length) { |
4869 if (length < 0 || length > FixedArray::kMaxLength) { | 4869 if (length < 0 || length > FixedArray::kMaxLength) { |
4870 return Failure::OutOfMemoryException(); | 4870 return Failure::OutOfMemoryException(0xd); |
4871 } | 4871 } |
4872 ASSERT(length > 0); | 4872 ASSERT(length > 0); |
4873 // Use the general function if we're forced to always allocate. | 4873 // Use the general function if we're forced to always allocate. |
4874 if (always_allocate()) return AllocateFixedArray(length, TENURED); | 4874 if (always_allocate()) return AllocateFixedArray(length, TENURED); |
4875 // Allocate the raw data for a fixed array. | 4875 // Allocate the raw data for a fixed array. |
4876 int size = FixedArray::SizeFor(length); | 4876 int size = FixedArray::SizeFor(length); |
4877 return size <= kMaxObjectSizeInNewSpace | 4877 return size <= kMaxObjectSizeInNewSpace |
4878 ? new_space_.AllocateRaw(size) | 4878 ? new_space_.AllocateRaw(size) |
4879 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); | 4879 : lo_space_->AllocateRaw(size, NOT_EXECUTABLE); |
4880 } | 4880 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4936 array->set_length(length); | 4936 array->set_length(length); |
4937 // Initialize body. | 4937 // Initialize body. |
4938 ASSERT(!InNewSpace(undefined_value())); | 4938 ASSERT(!InNewSpace(undefined_value())); |
4939 MemsetPointer(array->data_start(), undefined_value(), length); | 4939 MemsetPointer(array->data_start(), undefined_value(), length); |
4940 return result; | 4940 return result; |
4941 } | 4941 } |
4942 | 4942 |
4943 | 4943 |
4944 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { | 4944 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { |
4945 if (length < 0 || length > FixedArray::kMaxLength) { | 4945 if (length < 0 || length > FixedArray::kMaxLength) { |
4946 return Failure::OutOfMemoryException(); | 4946 return Failure::OutOfMemoryException(0xe); |
4947 } | 4947 } |
4948 | 4948 |
4949 AllocationSpace space = | 4949 AllocationSpace space = |
4950 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; | 4950 (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; |
4951 int size = FixedArray::SizeFor(length); | 4951 int size = FixedArray::SizeFor(length); |
4952 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { | 4952 if (space == NEW_SPACE && size > kMaxObjectSizeInNewSpace) { |
4953 // Too big for new space. | 4953 // Too big for new space. |
4954 space = LO_SPACE; | 4954 space = LO_SPACE; |
4955 } else if (space == OLD_POINTER_SPACE && | 4955 } else if (space == OLD_POINTER_SPACE && |
4956 size > Page::kMaxNonCodeHeapObjectSize) { | 4956 size > Page::kMaxNonCodeHeapObjectSize) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5069 | 5069 |
5070 elements->set_map_no_write_barrier(fixed_double_array_map()); | 5070 elements->set_map_no_write_barrier(fixed_double_array_map()); |
5071 elements->set_length(length); | 5071 elements->set_length(length); |
5072 return elements; | 5072 return elements; |
5073 } | 5073 } |
5074 | 5074 |
5075 | 5075 |
5076 MaybeObject* Heap::AllocateRawFixedDoubleArray(int length, | 5076 MaybeObject* Heap::AllocateRawFixedDoubleArray(int length, |
5077 PretenureFlag pretenure) { | 5077 PretenureFlag pretenure) { |
5078 if (length < 0 || length > FixedDoubleArray::kMaxLength) { | 5078 if (length < 0 || length > FixedDoubleArray::kMaxLength) { |
5079 return Failure::OutOfMemoryException(); | 5079 return Failure::OutOfMemoryException(0xf); |
5080 } | 5080 } |
5081 | 5081 |
5082 AllocationSpace space = | 5082 AllocationSpace space = |
5083 (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; | 5083 (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; |
5084 int size = FixedDoubleArray::SizeFor(length); | 5084 int size = FixedDoubleArray::SizeFor(length); |
5085 | 5085 |
5086 #ifndef V8_HOST_ARCH_64_BIT | 5086 #ifndef V8_HOST_ARCH_64_BIT |
5087 size += kPointerSize; | 5087 size += kPointerSize; |
5088 #endif | 5088 #endif |
5089 | 5089 |
(...skipping 2266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7356 static_cast<int>(object_sizes_last_time_[index])); | 7356 static_cast<int>(object_sizes_last_time_[index])); |
7357 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) | 7357 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) |
7358 #undef ADJUST_LAST_TIME_OBJECT_COUNT | 7358 #undef ADJUST_LAST_TIME_OBJECT_COUNT |
7359 | 7359 |
7360 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); | 7360 memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); |
7361 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); | 7361 memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); |
7362 ClearObjectStats(); | 7362 ClearObjectStats(); |
7363 } | 7363 } |
7364 | 7364 |
7365 } } // namespace v8::internal | 7365 } } // namespace v8::internal |
OLD | NEW |