| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index fa358c53929127218fbd4fd719d5bec8d3bab3b0..2866a5de890eccbabe5667d21b25c57b9970d5f4 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -3756,262 +3756,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();
|
| - } else 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);
|
| - }
|
| -
|
| - // Make an attempt to flatten the buffer to reduce access time.
|
| - buffer = buffer->TryFlattenGetString();
|
| -
|
| - 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();
|
|
|