Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1433)

Side by Side Diff: src/heap.cc

Issue 114943004: Reland "Handlify concat string and substring." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix test case. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after
3787 message->set_arguments(arguments); 3787 message->set_arguments(arguments);
3788 message->set_start_position(start_position); 3788 message->set_start_position(start_position);
3789 message->set_end_position(end_position); 3789 message->set_end_position(end_position);
3790 message->set_script(script); 3790 message->set_script(script);
3791 message->set_stack_trace(stack_trace); 3791 message->set_stack_trace(stack_trace);
3792 message->set_stack_frames(stack_frames); 3792 message->set_stack_frames(stack_frames);
3793 return result; 3793 return result;
3794 } 3794 }
3795 3795
3796 3796
3797
3798 // Returns true for a character in a range. Both limits are inclusive.
3799 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
3800 // This makes uses of the the unsigned wraparound.
3801 return character - from <= to - from;
3802 }
3803
3804
3805 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
3806 Heap* heap,
3807 uint16_t c1,
3808 uint16_t c2) {
3809 String* result;
3810 // Numeric strings have a different hash algorithm not known by
3811 // LookupTwoCharsStringIfExists, so we skip this step for such strings.
3812 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
3813 heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) {
3814 return result;
3815 // Now we know the length is 2, we might as well make use of that fact
3816 // when building the new string.
3817 } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
3818 // We can do this.
3819 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
3820 Object* result;
3821 { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
3822 if (!maybe_result->ToObject(&result)) return maybe_result;
3823 }
3824 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3825 dest[0] = static_cast<uint8_t>(c1);
3826 dest[1] = static_cast<uint8_t>(c2);
3827 return result;
3828 } else {
3829 Object* result;
3830 { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
3831 if (!maybe_result->ToObject(&result)) return maybe_result;
3832 }
3833 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
3834 dest[0] = c1;
3835 dest[1] = c2;
3836 return result;
3837 }
3838 }
3839
3840
3841 MaybeObject* Heap::AllocateConsString(String* first, String* second) {
3842 int first_length = first->length();
3843 if (first_length == 0) {
3844 return second;
3845 }
3846
3847 int second_length = second->length();
3848 if (second_length == 0) {
3849 return first;
3850 }
3851
3852 int length = first_length + second_length;
3853
3854 // Optimization for 2-byte strings often used as keys in a decompression
3855 // dictionary. Check whether we already have the string in the string
3856 // table to prevent creation of many unneccesary strings.
3857 if (length == 2) {
3858 uint16_t c1 = first->Get(0);
3859 uint16_t c2 = second->Get(0);
3860 return MakeOrFindTwoCharacterString(this, c1, c2);
3861 }
3862
3863 bool first_is_one_byte = first->IsOneByteRepresentation();
3864 bool second_is_one_byte = second->IsOneByteRepresentation();
3865 bool is_one_byte = first_is_one_byte && second_is_one_byte;
3866 // Make sure that an out of memory exception is thrown if the length
3867 // of the new cons string is too large.
3868 if (length > String::kMaxLength || length < 0) {
3869 isolate()->context()->mark_out_of_memory();
3870 return Failure::OutOfMemoryException(0x4);
3871 }
3872
3873 bool is_one_byte_data_in_two_byte_string = false;
3874 if (!is_one_byte) {
3875 // At least one of the strings uses two-byte representation so we
3876 // can't use the fast case code for short ASCII strings below, but
3877 // we can try to save memory if all chars actually fit in ASCII.
3878 is_one_byte_data_in_two_byte_string =
3879 first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars();
3880 if (is_one_byte_data_in_two_byte_string) {
3881 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
3882 }
3883 }
3884
3885 // If the resulting string is small make a flat string.
3886 if (length < ConsString::kMinLength) {
3887 // Note that neither of the two inputs can be a slice because:
3888 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
3889 ASSERT(first->IsFlat());
3890 ASSERT(second->IsFlat());
3891 if (is_one_byte) {
3892 Object* result;
3893 { MaybeObject* maybe_result = AllocateRawOneByteString(length);
3894 if (!maybe_result->ToObject(&result)) return maybe_result;
3895 }
3896 // Copy the characters into the new object.
3897 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3898 // Copy first part.
3899 const uint8_t* src;
3900 if (first->IsExternalString()) {
3901 src = ExternalAsciiString::cast(first)->GetChars();
3902 } else {
3903 src = SeqOneByteString::cast(first)->GetChars();
3904 }
3905 for (int i = 0; i < first_length; i++) *dest++ = src[i];
3906 // Copy second part.
3907 if (second->IsExternalString()) {
3908 src = ExternalAsciiString::cast(second)->GetChars();
3909 } else {
3910 src = SeqOneByteString::cast(second)->GetChars();
3911 }
3912 for (int i = 0; i < second_length; i++) *dest++ = src[i];
3913 return result;
3914 } else {
3915 if (is_one_byte_data_in_two_byte_string) {
3916 Object* result;
3917 { MaybeObject* maybe_result = AllocateRawOneByteString(length);
3918 if (!maybe_result->ToObject(&result)) return maybe_result;
3919 }
3920 // Copy the characters into the new object.
3921 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3922 String::WriteToFlat(first, dest, 0, first_length);
3923 String::WriteToFlat(second, dest + first_length, 0, second_length);
3924 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
3925 return result;
3926 }
3927
3928 Object* result;
3929 { MaybeObject* maybe_result = AllocateRawTwoByteString(length);
3930 if (!maybe_result->ToObject(&result)) return maybe_result;
3931 }
3932 // Copy the characters into the new object.
3933 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
3934 String::WriteToFlat(first, dest, 0, first_length);
3935 String::WriteToFlat(second, dest + first_length, 0, second_length);
3936 return result;
3937 }
3938 }
3939
3940 Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ?
3941 cons_ascii_string_map() : cons_string_map();
3942
3943 Object* result;
3944 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
3945 if (!maybe_result->ToObject(&result)) return maybe_result;
3946 }
3947
3948 DisallowHeapAllocation no_gc;
3949 ConsString* cons_string = ConsString::cast(result);
3950 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
3951 cons_string->set_length(length);
3952 cons_string->set_hash_field(String::kEmptyHashField);
3953 cons_string->set_first(first, mode);
3954 cons_string->set_second(second, mode);
3955 return result;
3956 }
3957
3958
3959 MaybeObject* Heap::AllocateSubString(String* buffer,
3960 int start,
3961 int end,
3962 PretenureFlag pretenure) {
3963 int length = end - start;
3964 if (length <= 0) {
3965 return empty_string();
3966 }
3967
3968 // Make an attempt to flatten the buffer to reduce access time.
3969 buffer = buffer->TryFlattenGetString();
3970
3971 if (length == 1) {
3972 return LookupSingleCharacterStringFromCode(buffer->Get(start));
3973 } else if (length == 2) {
3974 // Optimization for 2-byte strings often used as keys in a decompression
3975 // dictionary. Check whether we already have the string in the string
3976 // table to prevent creation of many unnecessary strings.
3977 uint16_t c1 = buffer->Get(start);
3978 uint16_t c2 = buffer->Get(start + 1);
3979 return MakeOrFindTwoCharacterString(this, c1, c2);
3980 }
3981
3982 if (!FLAG_string_slices ||
3983 !buffer->IsFlat() ||
3984 length < SlicedString::kMinLength ||
3985 pretenure == TENURED) {
3986 Object* result;
3987 // WriteToFlat takes care of the case when an indirect string has a
3988 // different encoding from its underlying string. These encodings may
3989 // differ because of externalization.
3990 bool is_one_byte = buffer->IsOneByteRepresentation();
3991 { MaybeObject* maybe_result = is_one_byte
3992 ? AllocateRawOneByteString(length, pretenure)
3993 : AllocateRawTwoByteString(length, pretenure);
3994 if (!maybe_result->ToObject(&result)) return maybe_result;
3995 }
3996 String* string_result = String::cast(result);
3997 // Copy the characters into the new object.
3998 if (is_one_byte) {
3999 ASSERT(string_result->IsOneByteRepresentation());
4000 uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars();
4001 String::WriteToFlat(buffer, dest, start, end);
4002 } else {
4003 ASSERT(string_result->IsTwoByteRepresentation());
4004 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
4005 String::WriteToFlat(buffer, dest, start, end);
4006 }
4007 return result;
4008 }
4009
4010 ASSERT(buffer->IsFlat());
4011 #if VERIFY_HEAP
4012 if (FLAG_verify_heap) {
4013 buffer->StringVerify();
4014 }
4015 #endif
4016
4017 Object* result;
4018 // When slicing an indirect string we use its encoding for a newly created
4019 // slice and don't check the encoding of the underlying string. This is safe
4020 // even if the encodings are different because of externalization. If an
4021 // indirect ASCII string is pointing to a two-byte string, the two-byte char
4022 // codes of the underlying string must still fit into ASCII (because
4023 // externalization must not change char codes).
4024 { Map* map = buffer->IsOneByteRepresentation()
4025 ? sliced_ascii_string_map()
4026 : sliced_string_map();
4027 MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
4028 if (!maybe_result->ToObject(&result)) return maybe_result;
4029 }
4030
4031 DisallowHeapAllocation no_gc;
4032 SlicedString* sliced_string = SlicedString::cast(result);
4033 sliced_string->set_length(length);
4034 sliced_string->set_hash_field(String::kEmptyHashField);
4035 if (buffer->IsConsString()) {
4036 ConsString* cons = ConsString::cast(buffer);
4037 ASSERT(cons->second()->length() == 0);
4038 sliced_string->set_parent(cons->first());
4039 sliced_string->set_offset(start);
4040 } else if (buffer->IsSlicedString()) {
4041 // Prevent nesting sliced strings.
4042 SlicedString* parent_slice = SlicedString::cast(buffer);
4043 sliced_string->set_parent(parent_slice->parent());
4044 sliced_string->set_offset(start + parent_slice->offset());
4045 } else {
4046 sliced_string->set_parent(buffer);
4047 sliced_string->set_offset(start);
4048 }
4049 ASSERT(sliced_string->parent()->IsSeqString() ||
4050 sliced_string->parent()->IsExternalString());
4051 return result;
4052 }
4053
4054
4055 MaybeObject* Heap::AllocateExternalStringFromAscii( 3797 MaybeObject* Heap::AllocateExternalStringFromAscii(
4056 const ExternalAsciiString::Resource* resource) { 3798 const ExternalAsciiString::Resource* resource) {
4057 size_t length = resource->length(); 3799 size_t length = resource->length();
4058 if (length > static_cast<size_t>(String::kMaxLength)) { 3800 if (length > static_cast<size_t>(String::kMaxLength)) {
4059 isolate()->context()->mark_out_of_memory(); 3801 isolate()->context()->mark_out_of_memory();
4060 return Failure::OutOfMemoryException(0x5); 3802 return Failure::OutOfMemoryException(0x5);
4061 } 3803 }
4062 3804
4063 Map* map = external_ascii_string_map(); 3805 Map* map = external_ascii_string_map();
4064 Object* result; 3806 Object* result;
(...skipping 3894 matching lines...) Expand 10 before | Expand all | Expand 10 after
7959 static_cast<int>(object_sizes_last_time_[index])); 7701 static_cast<int>(object_sizes_last_time_[index]));
7960 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) 7702 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT)
7961 #undef ADJUST_LAST_TIME_OBJECT_COUNT 7703 #undef ADJUST_LAST_TIME_OBJECT_COUNT
7962 7704
7963 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); 7705 OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
7964 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); 7706 OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
7965 ClearObjectStats(); 7707 ClearObjectStats();
7966 } 7708 }
7967 7709
7968 } } // namespace v8::internal 7710 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698