Index: src/heap.cc |
diff --git a/src/heap.cc b/src/heap.cc |
index 6921bb653f8a97c905fcc0800736c5044e6e38d4..d4ae9893008aeea9bf5a4561bab3ac4ae409a0d1 100644 |
--- a/src/heap.cc |
+++ b/src/heap.cc |
@@ -3794,264 +3794,6 @@ MaybeObject* Heap::AllocateJSMessageObject(String* type, |
} |
- |
-// Returns true for a character in a range. Both limits are inclusive. |
-static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { |
- // This makes uses of the the unsigned wraparound. |
- return character - from <= to - from; |
-} |
- |
- |
-MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( |
- Heap* heap, |
- uint16_t c1, |
- uint16_t c2) { |
- String* result; |
- // Numeric strings have a different hash algorithm not known by |
- // LookupTwoCharsStringIfExists, so we skip this step for such strings. |
- if ((!Between(c1, '0', '9') || !Between(c2, '0', '9')) && |
- heap->string_table()->LookupTwoCharsStringIfExists(c1, c2, &result)) { |
- return result; |
- // Now we know the length is 2, we might as well make use of that fact |
- // when building the new string. |
- } else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) { |
- // We can do this. |
- ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this. |
- Object* result; |
- { MaybeObject* maybe_result = heap->AllocateRawOneByteString(2); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); |
- dest[0] = static_cast<uint8_t>(c1); |
- dest[1] = static_cast<uint8_t>(c2); |
- return result; |
- } else { |
- Object* result; |
- { MaybeObject* maybe_result = heap->AllocateRawTwoByteString(2); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
- dest[0] = c1; |
- dest[1] = c2; |
- return result; |
- } |
-} |
- |
- |
-MaybeObject* Heap::AllocateConsString(String* first, String* second) { |
- int first_length = first->length(); |
- if (first_length == 0) { |
- return second; |
- } |
- |
- int second_length = second->length(); |
- if (second_length == 0) { |
- return first; |
- } |
- |
- int length = first_length + second_length; |
- |
- // Optimization for 2-byte strings often used as keys in a decompression |
- // dictionary. Check whether we already have the string in the string |
- // table to prevent creation of many unneccesary strings. |
- if (length == 2) { |
- uint16_t c1 = first->Get(0); |
- uint16_t c2 = second->Get(0); |
- return MakeOrFindTwoCharacterString(this, c1, c2); |
- } |
- |
- bool first_is_one_byte = first->IsOneByteRepresentation(); |
- bool second_is_one_byte = second->IsOneByteRepresentation(); |
- bool is_one_byte = first_is_one_byte && second_is_one_byte; |
- // Make sure that an out of memory exception is thrown if the length |
- // of the new cons string is too large. |
- if (length > String::kMaxLength || length < 0) { |
- isolate()->context()->mark_out_of_memory(); |
- return Failure::OutOfMemoryException(0x4); |
- } |
- |
- bool is_one_byte_data_in_two_byte_string = false; |
- if (!is_one_byte) { |
- // At least one of the strings uses two-byte representation so we |
- // can't use the fast case code for short ASCII strings below, but |
- // we can try to save memory if all chars actually fit in ASCII. |
- is_one_byte_data_in_two_byte_string = |
- first->HasOnlyOneByteChars() && second->HasOnlyOneByteChars(); |
- if (is_one_byte_data_in_two_byte_string) { |
- isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); |
- } |
- } |
- |
- // If the resulting string is small make a flat string. |
- if (length < ConsString::kMinLength) { |
- // Note that neither of the two inputs can be a slice because: |
- STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength); |
- ASSERT(first->IsFlat()); |
- ASSERT(second->IsFlat()); |
- if (is_one_byte) { |
- Object* result; |
- { MaybeObject* maybe_result = AllocateRawOneByteString(length); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- // Copy the characters into the new object. |
- uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); |
- // Copy first part. |
- const uint8_t* src; |
- if (first->IsExternalString()) { |
- src = ExternalAsciiString::cast(first)->GetChars(); |
- } else { |
- src = SeqOneByteString::cast(first)->GetChars(); |
- } |
- for (int i = 0; i < first_length; i++) *dest++ = src[i]; |
- // Copy second part. |
- if (second->IsExternalString()) { |
- src = ExternalAsciiString::cast(second)->GetChars(); |
- } else { |
- src = SeqOneByteString::cast(second)->GetChars(); |
- } |
- for (int i = 0; i < second_length; i++) *dest++ = src[i]; |
- return result; |
- } else { |
- if (is_one_byte_data_in_two_byte_string) { |
- Object* result; |
- { MaybeObject* maybe_result = AllocateRawOneByteString(length); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- // Copy the characters into the new object. |
- uint8_t* dest = SeqOneByteString::cast(result)->GetChars(); |
- String::WriteToFlat(first, dest, 0, first_length); |
- String::WriteToFlat(second, dest + first_length, 0, second_length); |
- isolate_->counters()->string_add_runtime_ext_to_ascii()->Increment(); |
- return result; |
- } |
- |
- Object* result; |
- { MaybeObject* maybe_result = AllocateRawTwoByteString(length); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- // Copy the characters into the new object. |
- uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
- String::WriteToFlat(first, dest, 0, first_length); |
- String::WriteToFlat(second, dest + first_length, 0, second_length); |
- return result; |
- } |
- } |
- |
- Map* map = (is_one_byte || is_one_byte_data_in_two_byte_string) ? |
- cons_ascii_string_map() : cons_string_map(); |
- |
- Object* result; |
- { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- |
- DisallowHeapAllocation no_gc; |
- ConsString* cons_string = ConsString::cast(result); |
- WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc); |
- cons_string->set_length(length); |
- cons_string->set_hash_field(String::kEmptyHashField); |
- cons_string->set_first(first, mode); |
- cons_string->set_second(second, mode); |
- return result; |
-} |
- |
- |
-MaybeObject* Heap::AllocateSubString(String* buffer, |
- int start, |
- int end, |
- PretenureFlag pretenure) { |
- int length = end - start; |
- if (length <= 0) { |
- return empty_string(); |
- } |
- |
- // Make an attempt to flatten the buffer to reduce access time. |
- buffer = buffer->TryFlattenGetString(); |
- |
- if (length == 1) { |
- return LookupSingleCharacterStringFromCode(buffer->Get(start)); |
- } else if (length == 2) { |
- // Optimization for 2-byte strings often used as keys in a decompression |
- // dictionary. Check whether we already have the string in the string |
- // table to prevent creation of many unnecessary strings. |
- uint16_t c1 = buffer->Get(start); |
- uint16_t c2 = buffer->Get(start + 1); |
- return MakeOrFindTwoCharacterString(this, c1, c2); |
- } |
- |
- if (!FLAG_string_slices || |
- !buffer->IsFlat() || |
- length < SlicedString::kMinLength || |
- pretenure == TENURED) { |
- Object* result; |
- // WriteToFlat takes care of the case when an indirect string has a |
- // different encoding from its underlying string. These encodings may |
- // differ because of externalization. |
- bool is_one_byte = buffer->IsOneByteRepresentation(); |
- { MaybeObject* maybe_result = is_one_byte |
- ? AllocateRawOneByteString(length, pretenure) |
- : AllocateRawTwoByteString(length, pretenure); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- String* string_result = String::cast(result); |
- // Copy the characters into the new object. |
- if (is_one_byte) { |
- ASSERT(string_result->IsOneByteRepresentation()); |
- uint8_t* dest = SeqOneByteString::cast(string_result)->GetChars(); |
- String::WriteToFlat(buffer, dest, start, end); |
- } else { |
- ASSERT(string_result->IsTwoByteRepresentation()); |
- uc16* dest = SeqTwoByteString::cast(string_result)->GetChars(); |
- String::WriteToFlat(buffer, dest, start, end); |
- } |
- return result; |
- } |
- |
- ASSERT(buffer->IsFlat()); |
-#if VERIFY_HEAP |
- if (FLAG_verify_heap) { |
- buffer->StringVerify(); |
- } |
-#endif |
- |
- Object* result; |
- // When slicing an indirect string we use its encoding for a newly created |
- // slice and don't check the encoding of the underlying string. This is safe |
- // even if the encodings are different because of externalization. If an |
- // indirect ASCII string is pointing to a two-byte string, the two-byte char |
- // codes of the underlying string must still fit into ASCII (because |
- // externalization must not change char codes). |
- { Map* map = buffer->IsOneByteRepresentation() |
- ? sliced_ascii_string_map() |
- : sliced_string_map(); |
- MaybeObject* maybe_result = Allocate(map, NEW_SPACE); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
- } |
- |
- DisallowHeapAllocation no_gc; |
- SlicedString* sliced_string = SlicedString::cast(result); |
- sliced_string->set_length(length); |
- sliced_string->set_hash_field(String::kEmptyHashField); |
- if (buffer->IsConsString()) { |
- ConsString* cons = ConsString::cast(buffer); |
- ASSERT(cons->second()->length() == 0); |
- sliced_string->set_parent(cons->first()); |
- sliced_string->set_offset(start); |
- } else if (buffer->IsSlicedString()) { |
- // Prevent nesting sliced strings. |
- SlicedString* parent_slice = SlicedString::cast(buffer); |
- sliced_string->set_parent(parent_slice->parent()); |
- sliced_string->set_offset(start + parent_slice->offset()); |
- } else { |
- sliced_string->set_parent(buffer); |
- sliced_string->set_offset(start); |
- } |
- ASSERT(sliced_string->parent()->IsSeqString() || |
- sliced_string->parent()->IsExternalString()); |
- return result; |
-} |
- |
- |
MaybeObject* Heap::AllocateExternalStringFromAscii( |
const ExternalAsciiString::Resource* resource) { |
size_t length = resource->length(); |