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

Side by Side Diff: src/heap.cc

Issue 59973004: Revert "Handlify concat string and substring." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 1 month 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 3756 matching lines...) Expand 10 before | Expand all | Expand 10 after
3767 message->set_arguments(arguments); 3767 message->set_arguments(arguments);
3768 message->set_start_position(start_position); 3768 message->set_start_position(start_position);
3769 message->set_end_position(end_position); 3769 message->set_end_position(end_position);
3770 message->set_script(script); 3770 message->set_script(script);
3771 message->set_stack_trace(stack_trace); 3771 message->set_stack_trace(stack_trace);
3772 message->set_stack_frames(stack_frames); 3772 message->set_stack_frames(stack_frames);
3773 return result; 3773 return result;
3774 } 3774 }
3775 3775
3776 3776
3777
3778 // Returns true for a character in a range. Both limits are inclusive.
3779 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
3780 // This makes uses of the the unsigned wraparound.
3781 return character - from <= to - from;
3782 }
3783
3784
3785 MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
3786 Heap* heap,
3787 uint16_t c1,
3788 uint16_t c2) {
3789 String* result;
3790 // Numeric strings have a different hash algorithm not known by
3791 // LookupTwoCharsStringIfExists, so we skip this step for such strings.
3792 if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) &&
3793 heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) {
3794 return result;
3795 // Now we know the length is 2, we might as well make use of that fact
3796 // when building the new string.
3797 } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
3798 // We can do this.
3799 ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
3800 Object* result;
3801 { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
3802 if (!maybe_result->ToObject(&result)) return maybe_result;
3803 }
3804 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3805 dest[0] = static_cast<uint8_t>(c1);
3806 dest[1] = static_cast<uint8_t>(c2);
3807 return result;
3808 } else {
3809 Object* result;
3810 { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2);
3811 if (!maybe_result->ToObject(&result)) return maybe_result;
3812 }
3813 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
3814 dest[0] = c1;
3815 dest[1] = c2;
3816 return result;
3817 }
3818 }
3819
3820
3821 MaybeObject* Heap::AllocateConsString(String* first, String* second) {
3822 int first_length = first->length();
3823 if (first_length == 0) {
3824 return second;
3825 }
3826
3827 int second_length = second->length();
3828 if (second_length == 0) {
3829 return first;
3830 }
3831
3832 int length = first_length + second_length;
3833
3834 // Optimization for 2-byte strings often used as keys in a decompression
3835 // dictionary. Check whether we already have the string in the string
3836 // table to prevent creation of many unneccesary strings.
3837 if (length == 2) {
3838 uint16_t c1 = first->Get(0);
3839 uint16_t c2 = second->Get(0);
3840 return MakeOrFindTwoCharacterString(this, c1, c2);
3841 }
3842
3843 bool first_is_one_byte = first->IsOneByteRepresentation();
3844 bool second_is_one_byte = second->IsOneByteRepresentation();
3845 bool is_one_byte = first_is_one_byte && second_is_one_byte;
3846 // Make sure that an out of memory exception is thrown if the length
3847 // of the new cons string is too large.
3848 if (length > String::kMaxLength || length < 0) {
3849 isolate()->context()->mark_out_of_memory();
3850 return Failure::OutOfMemoryException(0x4);
3851 }
3852
3853 bool is_one_byte_data_in_two_byte_string = false;
3854 if (!is_one_byte) {
3855 // At least one of the strings uses two-byte representation so we
3856 // can't use the fast case code for short ASCII strings below, but
3857 // we can try to save memory if all chars actually fit in ASCII.
3858 is_one_byte_data_in_two_byte_string =
3859 first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars();
3860 if (is_one_byte_data_in_two_byte_string) {
3861 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
3862 }
3863 }
3864
3865 // If the resulting string is small make a flat string.
3866 if (length < ConsString::kMinLength) {
3867 // Note that neither of the two inputs can be a slice because:
3868 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
3869 ASSERT(first->IsFlat());
3870 ASSERT(second->IsFlat());
3871 if (is_one_byte) {
3872 Object* result;
3873 { MaybeObject* maybe_result = AllocateRawOneByteString(length);
3874 if (!maybe_result->ToObject(&result)) return maybe_result;
3875 }
3876 // Copy the characters into the new object.
3877 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3878 // Copy first part.
3879 const uint8_t* src;
3880 if (first->IsExternalString()) {
3881 src = ExternalAsciiString::cast(first)->GetChars();
3882 } else {
3883 src = SeqOneByteString::cast(first)->GetChars();
3884 }
3885 for (int i = 0; i < first_length; i++) *dest++ = src[i];
3886 // Copy second part.
3887 if (second->IsExternalString()) {
3888 src = ExternalAsciiString::cast(second)->GetChars();
3889 } else {
3890 src = SeqOneByteString::cast(second)->GetChars();
3891 }
3892 for (int i = 0; i < second_length; i++) *dest++ = src[i];
3893 return result;
3894 } else {
3895 if (is_one_byte_data_in_two_byte_string) {
3896 Object* result;
3897 { MaybeObject* maybe_result = AllocateRawOneByteString(length);
3898 if (!maybe_result->ToObject(&result)) return maybe_result;
3899 }
3900 // Copy the characters into the new object.
3901 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
3902 String::WriteToFlat(first, dest, 0, first_length);
3903 String::WriteToFlat(second, dest + first_length, 0, second_length);
3904 isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment();
3905 return result;
3906 }
3907
3908 Object* result;
3909 { MaybeObject* maybe_result = AllocateRawTwoByteString(length);
3910 if (!maybe_result->ToObject(&result)) return maybe_result;
3911 }
3912 // Copy the characters into the new object.
3913 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
3914 String::WriteToFlat(first, dest, 0, first_length);
3915 String::WriteToFlat(second, dest + first_length, 0, second_length);
3916 return result;
3917 }
3918 }
3919
3920 Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ?
3921 cons_ascii_string_map() : cons_string_map();
3922
3923 Object* result;
3924 { MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
3925 if (!maybe_result->ToObject(&result)) return maybe_result;
3926 }
3927
3928 DisallowHeapAllocation no_gc;
3929 ConsString* cons_string = ConsString::cast(result);
3930 WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
3931 cons_string->set_length(length);
3932 cons_string->set_hash_field(String::kEmptyHashField);
3933 cons_string->set_first(first, mode);
3934 cons_string->set_second(second, mode);
3935 return result;
3936 }
3937
3938
3939 MaybeObject* Heap::AllocateSubString(String* buffer,
3940 int start,
3941 int end,
3942 PretenureFlag pretenure) {
3943 int length = end - start;
3944 if (length <= 0) {
3945 return empty_string();
3946 } else if (length == 1) {
3947 return LookupSingleCharacterStringFromCode(buffer->Get(start));
3948 } else if (length == 2) {
3949 // Optimization for 2-byte strings often used as keys in a decompression
3950 // dictionary. Check whether we already have the string in the string
3951 // table to prevent creation of many unnecessary strings.
3952 uint16_t c1 = buffer->Get(start);
3953 uint16_t c2 = buffer->Get(start + 1);
3954 return MakeOrFindTwoCharacterString(this, c1, c2);
3955 }
3956
3957 // Make an attempt to flatten the buffer to reduce access time.
3958 buffer = buffer->TryFlattenGetString();
3959
3960 if (!FLAG_string_slices ||
3961 !buffer->IsFlat() ||
3962 length < SlicedString::kMinLength ||
3963 pretenure == TENURED) {
3964 Object* result;
3965 // WriteToFlat takes care of the case when an indirect string has a
3966 // different encoding from its underlying string. These encodings may
3967 // differ because of externalization.
3968 bool is_one_byte = buffer->IsOneByteRepresentation();
3969 { MaybeObject* maybe_result = is_one_byte
3970 ? AllocateRawOneByteString(length, pretenure)
3971 : AllocateRawTwoByteString(length, pretenure);
3972 if (!maybe_result->ToObject(&result)) return maybe_result;
3973 }
3974 String* string_result = String::cast(result);
3975 // Copy the characters into the new object.
3976 if (is_one_byte) {
3977 ASSERT(string_result->IsOneByteRepresentation());
3978 uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars();
3979 String::WriteToFlat(buffer, dest, start, end);
3980 } else {
3981 ASSERT(string_result->IsTwoByteRepresentation());
3982 uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
3983 String::WriteToFlat(buffer, dest, start, end);
3984 }
3985 return result;
3986 }
3987
3988 ASSERT(buffer->IsFlat());
3989 #if VERIFY_HEAP
3990 if (FLAG_verify_heap) {
3991 buffer->StringVerify();
3992 }
3993 #endif
3994
3995 Object* result;
3996 // When slicing an indirect string we use its encoding for a newly created
3997 // slice and don't check the encoding of the underlying string. This is safe
3998 // even if the encodings are different because of externalization. If an
3999 // indirect ASCII string is pointing to a two-byte string, the two-byte char
4000 // codes of the underlying string must still fit into ASCII (because
4001 // externalization must not change char codes).
4002 { Map* map = buffer->IsOneByteRepresentation()
4003 ? sliced_ascii_string_map()
4004 : sliced_string_map();
4005 MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
4006 if (!maybe_result->ToObject(&result)) return maybe_result;
4007 }
4008
4009 DisallowHeapAllocation no_gc;
4010 SlicedString* sliced_string = SlicedString::cast(result);
4011 sliced_string->set_length(length);
4012 sliced_string->set_hash_field(String::kEmptyHashField);
4013 if (buffer->IsConsString()) {
4014 ConsString* cons = ConsString::cast(buffer);
4015 ASSERT(cons->second()->length() == 0);
4016 sliced_string->set_parent(cons->first());
4017 sliced_string->set_offset(start);
4018 } else if (buffer->IsSlicedString()) {
4019 // Prevent nesting sliced strings.
4020 SlicedString* parent_slice = SlicedString::cast(buffer);
4021 sliced_string->set_parent(parent_slice->parent());
4022 sliced_string->set_offset(start + parent_slice->offset());
4023 } else {
4024 sliced_string->set_parent(buffer);
4025 sliced_string->set_offset(start);
4026 }
4027 ASSERT(sliced_string->parent()->IsSeqString() ||
4028 sliced_string->parent()->IsExternalString());
4029 return result;
4030 }
4031
4032
3777 MaybeObject* Heap::AllocateExternalStringFromAscii( 4033 MaybeObject* Heap::AllocateExternalStringFromAscii(
3778 const ExternalAsciiString::Resource* resource) { 4034 const ExternalAsciiString::Resource* resource) {
3779 size_t length = resource->length(); 4035 size_t length = resource->length();
3780 if (length > static_cast<size_t>(String::kMaxLength)) { 4036 if (length > static_cast<size_t>(String::kMaxLength)) {
3781 isolate()->context()->mark_out_of_memory(); 4037 isolate()->context()->mark_out_of_memory();
3782 return Failure::OutOfMemoryException(0x5); 4038 return Failure::OutOfMemoryException(0x5);
3783 } 4039 }
3784 4040
3785 Map* map = external_ascii_string_map(); 4041 Map* map = external_ascii_string_map();
3786 Object* result; 4042 Object* result;
(...skipping 3861 matching lines...) Expand 10 before | Expand all | Expand 10 after
7648 if (FLAG_concurrent_recompilation) { 7904 if (FLAG_concurrent_recompilation) {
7649 heap_->relocation_mutex_->Lock(); 7905 heap_->relocation_mutex_->Lock();
7650 #ifdef DEBUG 7906 #ifdef DEBUG
7651 heap_->relocation_mutex_locked_by_optimizer_thread_ = 7907 heap_->relocation_mutex_locked_by_optimizer_thread_ =
7652 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread(); 7908 heap_->isolate()->optimizing_compiler_thread()->IsOptimizerThread();
7653 #endif // DEBUG 7909 #endif // DEBUG
7654 } 7910 }
7655 } 7911 }
7656 7912
7657 } } // namespace v8::internal 7913 } } // 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