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

Side by Side Diff: src/heap.cc

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