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

Unified Diff: src/objects.cc

Issue 6342: Specialized string equality based on representation (Closed)
Patch Set: Created 12 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
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index c5399fa137d7b66ea330afc0c7106517a570da92..2374d397f10dc33d10b09b1a923f5b9d84853691 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -522,7 +522,7 @@ Object* String::Flatten() {
// an old space GC.
PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
int len = length();
- Object* object = IsAscii() ?
+ Object* object = IsAsciiRepresentation() ?
Heap::AllocateRawAsciiString(len, tenure) :
Heap::AllocateRawTwoByteString(len, tenure);
if (object->IsFailure()) return object;
@@ -755,10 +755,10 @@ int HeapObject::SlowSizeFromMap(Map* map) {
if (instance_type < FIRST_NONSTRING_TYPE
&& (reinterpret_cast<String*>(this)->map_representation_tag(map)
== kSeqStringTag)) {
- if (reinterpret_cast<String*>(this)->is_ascii_map(map)) {
- return reinterpret_cast<AsciiString*>(this)->AsciiStringSize(map);
+ if (reinterpret_cast<String*>(this)->is_ascii_representation_map(map)) {
+ return reinterpret_cast<SeqAsciiString*>(this)->AsciiStringSize(map);
} else {
- return reinterpret_cast<TwoByteString*>(this)->TwoByteStringSize(map);
+ return reinterpret_cast<SeqTwoByteString*>(this)->TwoByteStringSize(map);
}
}
@@ -2970,7 +2970,7 @@ bool String::LooksValid() {
int String::Utf8Length() {
- if (is_ascii()) return length();
+ if (is_ascii_representation()) return length();
// Attempt to flatten before accessing the string. It probably
// doesn't make Utf8Length faster, but it is very likely that
// the string will be accessed later (for example by WriteUtf8)
@@ -2985,6 +2985,69 @@ int String::Utf8Length() {
}
+Vector<const char> String::ToAsciiVector() {
+ ASSERT(IsAsciiRepresentation());
+ ASSERT(IsFlat());
+
+ int offset = 0;
+ int length = this->length();
+ StringRepresentationTag string_tag = representation_tag();
+ String* string = this;
+ if (string_tag == kSlicedStringTag) {
+ SlicedString* sliced = SlicedString::cast(string);
+ offset += sliced->start();
+ string = String::cast(sliced->buffer());
+ string_tag = string->representation_tag();
+ } else if (string_tag == kConsStringTag) {
+ ConsString* cons = ConsString::cast(string);
+ ASSERT(String::cast(cons->second())->length() == 0);
+ string = String::cast(cons->first());
+ string_tag = string->representation_tag();
+ }
+ if (string_tag == kSeqStringTag) {
+ SeqAsciiString* seq = SeqAsciiString::cast(string);
+ char* start = reinterpret_cast<char*>(seq->GetCharsAddress());
+ return Vector<const char>(start + offset, length);
+ }
+ ASSERT(string_tag == kExternalStringTag);
+ ExternalAsciiString* ext = ExternalAsciiString::cast(string);
+ const char* start = ext->resource()->data();
+ return Vector<const char>(start + offset, length);
+}
+
+
+Vector<const uc16> String::ToUC16Vector() {
+ ASSERT(IsTwoByteStringRepresentation());
+ ASSERT(IsFlat());
+
+ int offset = 0;
+ int length = this->length();
+ StringRepresentationTag string_tag = representation_tag();
+ String* string = this;
+ if (string_tag == kSlicedStringTag) {
+ SlicedString* sliced = SlicedString::cast(string);
+ offset += sliced->start();
+ string = String::cast(sliced->buffer());
+ string_tag = string->representation_tag();
+ } else if (string_tag == kConsStringTag) {
+ ConsString* cons = ConsString::cast(string);
+ ASSERT(String::cast(cons->second())->length() == 0);
+ string = String::cast(cons->first());
+ string_tag = string->representation_tag();
+ }
+ if (string_tag == kSeqStringTag) {
+ SeqTwoByteString* seq = SeqTwoByteString::cast(string);
+ uc16* start = reinterpret_cast<uc16*>(seq->GetCharsAddress());
+ return Vector<const uc16>(start + offset, length);
+ }
+ ASSERT(string_tag == kExternalStringTag);
+ ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
+ const uc16* start =
+ reinterpret_cast<const uc16*>(ext->resource()->data());
+ return Vector<const uc16>(start + offset, length);
+}
+
+
SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
RobustnessFlag robust_flag,
int offset,
@@ -3051,10 +3114,10 @@ const uc16* String::GetTwoByteData() {
const uc16* String::GetTwoByteData(unsigned start) {
- ASSERT(!IsAscii());
+ ASSERT(!IsAsciiRepresentation());
switch (representation_tag()) {
case kSeqStringTag:
- return TwoByteString::cast(this)->TwoByteStringGetData(start);
+ return SeqTwoByteString::cast(this)->TwoByteStringGetData(start);
case kExternalStringTag:
return ExternalTwoByteString::cast(this)->
ExternalTwoByteStringGetData(start);
@@ -3100,13 +3163,13 @@ SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
}
-const uc16* TwoByteString::TwoByteStringGetData(unsigned start) {
+const uc16* SeqTwoByteString::TwoByteStringGetData(unsigned start) {
return reinterpret_cast<uc16*>(
reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
}
-void TwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+void SeqTwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
unsigned chars_read = 0;
@@ -3139,7 +3202,7 @@ void TwoByteString::TwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
}
-const unibrow::byte* AsciiString::AsciiStringReadBlock(unsigned* remaining,
+const unibrow::byte* SeqAsciiString::AsciiStringReadBlock(unsigned* remaining,
unsigned* offset_ptr,
unsigned max_chars) {
// Cast const char* to unibrow::byte* (signedness difference).
@@ -3301,7 +3364,7 @@ void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
}
-void AsciiString::AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
+void SeqAsciiString::AsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
unsigned* offset_ptr,
unsigned max_chars) {
unsigned capacity = rbb->capacity - rbb->cursor;
@@ -3346,12 +3409,12 @@ const unibrow::byte* String::ReadBlock(String* input,
}
switch (input->representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii()) {
- return AsciiString::cast(input)->AsciiStringReadBlock(&rbb->remaining,
+ if (input->is_ascii_representation()) {
+ return SeqAsciiString::cast(input)->AsciiStringReadBlock(&rbb->remaining,
offset_ptr,
max_chars);
} else {
- TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
+ SeqTwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
return rbb->util_buffer;
@@ -3365,7 +3428,7 @@ const unibrow::byte* String::ReadBlock(String* input,
offset_ptr,
max_chars);
case kExternalStringTag:
- if (input->is_ascii()) {
+ if (input->is_ascii_representation()) {
return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
&rbb->remaining,
offset_ptr,
@@ -3409,13 +3472,13 @@ void String::ReadBlockIntoBuffer(String* input,
switch (input->representation_tag()) {
case kSeqStringTag:
- if (input->is_ascii()) {
- AsciiString::cast(input)->AsciiStringReadBlockIntoBuffer(rbb,
+ if (input->is_ascii_representation()) {
+ SeqAsciiString::cast(input)->AsciiStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
return;
} else {
- TwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
+ SeqTwoByteString::cast(input)->TwoByteStringReadBlockIntoBuffer(rbb,
offset_ptr,
max_chars);
return;
@@ -3431,7 +3494,7 @@ void String::ReadBlockIntoBuffer(String* input,
max_chars);
return;
case kExternalStringTag:
- if (input->is_ascii()) {
+ if (input->is_ascii_representation()) {
ExternalAsciiString::cast(input)->
ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
} else {
@@ -3688,6 +3751,43 @@ uint16_t SlicedString::SlicedStringGet(int index) {
}
+template <typename IteratorA, typename IteratorB>
+static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
+ // General slow case check. We know that the ia and ib iterators
+ // have the same length.
+ while (ia->has_more()) {
+ uc32 ca = ia->GetNext();
+ uc32 cb = ib->GetNext();
+ if (ca != cb)
+ return false;
+ }
+ return true;
+}
+
+
+static StringInputBuffer string_compare_buffer_b;
+
+
+template <typename IteratorA>
+static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
+ if (b->IsFlat()) {
+ if (b->IsAsciiRepresentation()) {
+ VectorIterator<const char> ib(b->ToAsciiVector());
+ return CompareStringContents(ia, &ib);
+ } else {
+ VectorIterator<const uc16> ib(b->ToUC16Vector());
+ return CompareStringContents(ia, &ib);
+ }
+ } else {
+ string_compare_buffer_b.Reset(0, b);
+ return CompareStringContents(ia, &string_compare_buffer_b);
+ }
+}
+
+
+static StringInputBuffer string_compare_buffer_a;
+
+
bool String::SlowEquals(String* other) {
// Fast check: negative check with lengths.
int len = length();
@@ -3700,24 +3800,18 @@ bool String::SlowEquals(String* other) {
if (Hash() != other->Hash()) return false;
}
- // Fast case: avoid input buffers for small strings.
- const int kMaxLenthForFastCaseCheck = 5;
- for (int i = 0; i < kMaxLenthForFastCaseCheck; i++) {
- if (Get(i) != other->Get(i)) return false;
- if (i + 1 == len) return true;
- }
-
- // General slow case check.
- static StringInputBuffer buf1;
- static StringInputBuffer buf2;
- buf1.Reset(kMaxLenthForFastCaseCheck, this);
- buf2.Reset(kMaxLenthForFastCaseCheck, other);
- while (buf1.has_more()) {
- if (buf1.GetNext() != buf2.GetNext()) {
- return false;
+ if (this->IsFlat()) {
+ if (this->IsAsciiRepresentation()) {
+ VectorIterator<const char> buf1(this->ToAsciiVector());
+ return CompareStringContentsPartial(&buf1, other);
+ } else {
+ VectorIterator<const uc16> buf1(this->ToUC16Vector());
+ return CompareStringContentsPartial(&buf1, other);
}
+ } else {
+ string_compare_buffer_a.Reset(0, this);
+ return CompareStringContentsPartial(&string_compare_buffer_a, other);
}
- return true;
}
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698