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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index 2e4ef44ecdcd8fe1dd7b467043e497ee1ca99b6c..30932093be4763c09ebbe8b1498192ab8cbd5cee 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3774,6 +3774,262 @@ 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();
« 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