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

Unified Diff: src/factory.cc

Issue 50073005: Handlify concat string and substring. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 months 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/factory.h ('k') | src/handles.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 1dd246fc487431c7289047d3e62221d91bc866b6..909b5bf5632cbfa851e953173aad6038905986dd 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -284,11 +284,43 @@ Handle<SeqTwoByteString> Factory::NewRawTwoByteString(int length,
}
-Handle<String> Factory::NewConsString(Handle<String> first,
- Handle<String> second) {
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->AllocateConsString(*first, *second),
- String);
+// 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;
+}
+
+
+static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
+ uint16_t c1,
+ uint16_t c2) {
+ // 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')) {
+ String* result;
+ StringTable* table = isolate->heap()->string_table();
+ if (table->LookupTwoCharsStringIfExists(c1, c2, &result)) {
+ return handle(result);
+ }
+ }
+
+ // Now we know the length is 2, we might as well make use of that fact
+ // when building the new string.
+ if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
+ // We can do this.
+ ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
+ Handle<SeqOneByteString> str = isolate->factory()->NewRawOneByteString(2);
+ uint8_t* dest = str->GetChars();
+ dest[0] = static_cast<uint8_t>(c1);
+ dest[1] = static_cast<uint8_t>(c2);
+ return str;
+ } else {
+ Handle<SeqTwoByteString> str = isolate->factory()->NewRawTwoByteString(2);
+ uc16* dest = str->GetChars();
+ dest[0] = c1;
+ dest[1] = c2;
+ return str;
+ }
}
@@ -304,6 +336,99 @@ Handle<String> ConcatStringContent(Handle<StringType> result,
}
+Handle<ConsString> Factory::NewRawConsString(String::Encoding encoding) {
+ Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
+ ? cons_ascii_string_map() : cons_string_map();
+ CALL_HEAP_FUNCTION(isolate(),
+ isolate()->heap()->Allocate(*map, NEW_SPACE),
+ ConsString);
+}
+
+
+Handle<String> Factory::NewConsString(Handle<String> left,
+ Handle<String> right) {
+ int left_length = left->length();
+ if (left_length == 0) return right;
+ int right_length = right->length();
+ if (right_length == 0) return left;
+
+ int length = left_length + right_length;
+
+ if (length == 2) {
+ uint16_t c1 = left->Get(0);
+ uint16_t c2 = right->Get(0);
+ return MakeOrFindTwoCharacterString(isolate(), c1, c2);
+ }
+
+ // 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();
+ V8::FatalProcessOutOfMemory("String concatenation result too large.");
+ UNREACHABLE();
+ return Handle<String>::null();
+ }
+
+ bool left_is_one_byte = left->IsOneByteRepresentation();
+ bool right_is_one_byte = right->IsOneByteRepresentation();
+ bool is_one_byte = left_is_one_byte && right_is_one_byte;
+ 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 =
+ left->HasOnlyOneByteChars() && right->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(left->IsFlat());
+ ASSERT(right->IsFlat());
+
+ if (is_one_byte) {
+ Handle<SeqOneByteString> result = NewRawOneByteString(length);
+ DisallowHeapAllocation no_gc;
+ uint8_t* dest = result->GetChars();
+ // Copy left part.
+ const uint8_t* src = left->IsExternalString()
+ ? Handle<ExternalAsciiString>::cast(left)->GetChars()
+ : Handle<SeqOneByteString>::cast(left)->GetChars();
+ for (int i = 0; i < left_length; i++) *dest++ = src[i];
+ // Copy right part.
+ src = right->IsExternalString()
+ ? Handle<ExternalAsciiString>::cast(right)->GetChars()
+ : Handle<SeqOneByteString>::cast(right)->GetChars();
+ for (int i = 0; i < right_length; i++) *dest++ = src[i];
+ return result;
+ }
+
+ return (is_one_byte_data_in_two_byte_string)
+ ? ConcatStringContent<uint8_t>(NewRawOneByteString(length), left, right)
+ : ConcatStringContent<uc16>(NewRawTwoByteString(length), left, right);
+ }
+
+ Handle<ConsString> result = NewRawConsString(
+ (is_one_byte || is_one_byte_data_in_two_byte_string)
+ ? String::ONE_BYTE_ENCODING
+ : String::TWO_BYTE_ENCODING);
+
+ DisallowHeapAllocation no_gc;
+ WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
+
+ result->set_hash_field(String::kEmptyHashField);
+ result->set_length(length);
+ result->set_first(*left, mode);
+ result->set_second(*right, mode);
+ return result;
+}
+
+
Handle<String> Factory::NewFlatConcatString(Handle<String> first,
Handle<String> second) {
int total_length = first->length() + second->length();
@@ -318,22 +443,89 @@ Handle<String> Factory::NewFlatConcatString(Handle<String> first,
}
-Handle<String> Factory::NewSubString(Handle<String> str,
- int begin,
- int end) {
+Handle<SlicedString> Factory::NewRawSlicedString(String::Encoding encoding) {
+ Handle<Map> map = (encoding == String::ONE_BYTE_ENCODING)
+ ? sliced_ascii_string_map() : sliced_string_map();
CALL_HEAP_FUNCTION(isolate(),
- str->SubString(begin, end),
- String);
+ isolate()->heap()->Allocate(*map, NEW_SPACE),
+ SlicedString);
}
Handle<String> Factory::NewProperSubString(Handle<String> str,
int begin,
int end) {
+#if VERIFY_HEAP
+ if (FLAG_verify_heap) str->StringVerify();
+#endif
ASSERT(begin > 0 || end < str->length());
- CALL_HEAP_FUNCTION(isolate(),
- isolate()->heap()->AllocateSubString(*str, begin, end),
- String);
+
+ int length = end - begin;
+ if (length <= 0) return empty_string();
+ if (length == 1) {
+ return LookupSingleCharacterStringFromCode(isolate(), str->Get(begin));
+ }
+ 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 = str->Get(begin);
+ uint16_t c2 = str->Get(begin + 1);
+ return MakeOrFindTwoCharacterString(isolate(), c1, c2);
+ }
+
+ if (!FLAG_string_slices || length < SlicedString::kMinLength) {
+ if (str->IsOneByteRepresentation()) {
+ Handle<SeqOneByteString> result = NewRawOneByteString(length);
+ uint8_t* dest = result->GetChars();
+ DisallowHeapAllocation no_gc;
+ String::WriteToFlat(*str, dest, begin, end);
+ return result;
+ } else {
+ Handle<SeqTwoByteString> result = NewRawTwoByteString(length);
+ uc16* dest = result->GetChars();
+ DisallowHeapAllocation no_gc;
+ String::WriteToFlat(*str, dest, begin, end);
+ return result;
+ }
+ }
+
+ int offset = begin;
+
+ while (str->IsConsString()) {
+ Handle<ConsString> cons = Handle<ConsString>::cast(str);
+ int split = cons->first()->length();
+ if (split <= offset) {
+ // Slice is fully contained in the second part.
+ str = Handle<String>(cons->second(), isolate());
+ offset -= split; // Adjust for offset.
+ continue;
+ } else if (offset + length <= split) {
+ // Slice is fully contained in the first part.
+ str = Handle<String>(cons->first(), isolate());
+ continue;
+ }
+ break;
+ }
+
+ if (str->IsSlicedString()) {
+ Handle<SlicedString> slice = Handle<SlicedString>::cast(str);
+ str = Handle<String>(slice->parent(), isolate());
+ offset += slice->offset();
+ } else {
+ str = FlattenGetString(str);
+ }
+
+ ASSERT(str->IsSeqString() || str->IsExternalString());
+ Handle<SlicedString> slice = NewRawSlicedString(
+ str->IsOneByteRepresentation() ? String::ONE_BYTE_ENCODING
+ : String::TWO_BYTE_ENCODING);
+
+ slice->set_hash_field(String::kEmptyHashField);
+ slice->set_length(length);
+ slice->set_parent(*str);
+ slice->set_offset(offset);
+ return slice;
}
« no previous file with comments | « src/factory.h ('k') | src/handles.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698