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

Unified Diff: src/objects.cc

Issue 11727003: Reland r13275 and 13276 (Remove most uses of StringInputBuffer). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 12 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/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 e1d6da6df8518eb80212d79d311c3cfc4a76ea48..20553eb64bc94889c24418fab89dca2eeadf3346 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1048,7 +1048,8 @@ void String::StringShortPrint(StringStream* accumulator) {
return;
}
- StringInputBuffer buf(this);
+ ConsStringIteratorOp op;
+ StringCharacterStream stream(this, &op);
bool truncated = false;
if (len > kMaxShortPrintLength) {
@@ -1057,17 +1058,17 @@ void String::StringShortPrint(StringStream* accumulator) {
}
bool ascii = true;
for (int i = 0; i < len; i++) {
- int c = buf.GetNext();
+ uint16_t c = stream.GetNext();
if (c < 32 || c >= 127) {
ascii = false;
}
}
- buf.Reset(this);
+ stream.Reset(this);
if (ascii) {
accumulator->Add("<String[%u]: ", length());
for (int i = 0; i < len; i++) {
- accumulator->Put(buf.GetNext());
+ accumulator->Put(static_cast<char>(stream.GetNext()));
}
accumulator->Put('>');
} else {
@@ -1075,7 +1076,7 @@ void String::StringShortPrint(StringStream* accumulator) {
// characters and that backslashes are therefore escaped.
accumulator->Add("<String[%u]\\: ", length());
for (int i = 0; i < len; i++) {
- int c = buf.GetNext();
+ uint16_t c = stream.GetNext();
if (c == '\n') {
accumulator->Add("\\n");
} else if (c == '\r') {
@@ -1085,7 +1086,7 @@ void String::StringShortPrint(StringStream* accumulator) {
} else if (c < 32 || c > 126) {
accumulator->Add("\\x%02x", c);
} else {
- accumulator->Put(c);
+ accumulator->Put(static_cast<char>(c));
}
}
if (truncated) {
@@ -1537,15 +1538,16 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
}
-static bool IsIdentifier(UnicodeCache* cache,
- unibrow::CharacterStream* buffer) {
+static bool IsIdentifier(UnicodeCache* cache, String* string) {
// Checks whether the buffer contains an identifier (no escape).
- if (!buffer->has_more()) return false;
- if (!cache->IsIdentifierStart(buffer->GetNext())) {
+ if (string->length() == 0) return false;
+ ConsStringIteratorOp op;
+ StringCharacterStream stream(string, &op);
+ if (!cache->IsIdentifierStart(stream.GetNext())) {
return false;
}
- while (buffer->has_more()) {
- if (!cache->IsIdentifierPart(buffer->GetNext())) {
+ while (stream.HasMore()) {
+ if (!cache->IsIdentifierPart(stream.GetNext())) {
return false;
}
}
@@ -1566,8 +1568,7 @@ MaybeObject* JSObject::AddFastProperty(String* name,
// hidden symbols) and is not a real identifier.
// Normalize the object if it will have too many fast properties.
Isolate* isolate = GetHeap()->isolate();
- StringInputBuffer buffer(name);
- if ((!IsIdentifier(isolate->unicode_cache(), &buffer)
+ if ((!IsIdentifier(isolate->unicode_cache(), name)
&& name != isolate->heap()->hidden_symbol()) ||
(map()->unused_property_fields() == 0 &&
TooManyFastProperties(properties()->length(), store_mode))) {
@@ -6594,14 +6595,14 @@ SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
if (length < 0) length = kMaxInt - offset;
// Compute the size of the UTF-8 string. Start at the specified offset.
- Access<StringInputBuffer> buffer(
- heap->isolate()->objects_string_input_buffer());
- buffer->Reset(offset, this);
+ Access<ConsStringIteratorOp> op(
+ heap->isolate()->objects_string_iterator());
+ StringCharacterStream stream(this, op.value(), offset);
int character_position = offset;
int utf8_bytes = 0;
int last = unibrow::Utf16::kNoPreviousCharacter;
- while (buffer->has_more() && character_position++ < offset + length) {
- uint16_t character = buffer->GetNext();
+ while (stream.HasMore() && character_position++ < offset + length) {
+ uint16_t character = stream.GetNext();
utf8_bytes += unibrow::Utf8::Length(character, last);
last = character;
}
@@ -6613,13 +6614,12 @@ SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
char* result = NewArray<char>(utf8_bytes + 1);
// Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
- buffer->Rewind();
- buffer->Seek(offset);
+ stream.Reset(this, offset);
character_position = offset;
int utf8_byte_position = 0;
last = unibrow::Utf16::kNoPreviousCharacter;
- while (buffer->has_more() && character_position++ < offset + length) {
- uint16_t character = buffer->GetNext();
+ while (stream.HasMore() && character_position++ < offset + length) {
+ uint16_t character = stream.GetNext();
if (allow_nulls == DISALLOW_NULLS && character == 0) {
character = ' ';
}
@@ -6671,15 +6671,15 @@ SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
}
Heap* heap = GetHeap();
- Access<StringInputBuffer> buffer(
- heap->isolate()->objects_string_input_buffer());
- buffer->Reset(this);
+ Access<ConsStringIteratorOp> op(
+ heap->isolate()->objects_string_iterator());
+ StringCharacterStream stream(this, op.value());
uc16* result = NewArray<uc16>(length() + 1);
int i = 0;
- while (buffer->has_more()) {
- uint16_t character = buffer->GetNext();
+ while (stream.HasMore()) {
+ uint16_t character = stream.GetNext();
result[i++] = character;
}
result[i] = 0;
@@ -7457,46 +7457,28 @@ void String::WriteToFlat(String* src,
}
-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()) {
- uint32_t ca = ia->GetNext();
- uint32_t cb = ib->GetNext();
- ASSERT(ca <= unibrow::Utf16::kMaxNonSurrogateCharCode);
- ASSERT(cb <= unibrow::Utf16::kMaxNonSurrogateCharCode);
- if (ca != cb)
- return false;
- }
- return true;
-}
-
-
// Compares the contents of two strings by reading and comparing
// int-sized blocks of characters.
template <typename Char>
-static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
- int length = a.length();
- ASSERT_EQ(length, b.length());
- const Char* pa = a.start();
- const Char* pb = b.start();
+static inline bool CompareRawStringContents(const Char* const a,
+ const Char* const b,
+ int length) {
int i = 0;
#ifndef V8_HOST_CAN_READ_UNALIGNED
// If this architecture isn't comfortable reading unaligned ints
// then we have to check that the strings are aligned before
// comparing them blockwise.
const int kAlignmentMask = sizeof(uint32_t) - 1; // NOLINT
- uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
- uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
+ uint32_t pa_addr = reinterpret_cast<uint32_t>(a);
+ uint32_t pb_addr = reinterpret_cast<uint32_t>(b);
if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
#endif
const int kStepSize = sizeof(int) / sizeof(Char); // NOLINT
int endpoint = length - kStepSize;
// Compare blocks until we reach near the end of the string.
for (; i <= endpoint; i += kStepSize) {
- uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
- uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
+ uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
+ uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
if (wa != wb) {
return false;
}
@@ -7514,25 +7496,145 @@ static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
}
-template <typename IteratorA>
-static inline bool CompareStringContentsPartial(Isolate* isolate,
- IteratorA* ia,
- String* b) {
- String::FlatContent content = b->GetFlatContent();
- if (content.IsFlat()) {
- if (content.IsAscii()) {
- VectorIterator<char> ib(content.ToAsciiVector());
- return CompareStringContents(ia, &ib);
- } else {
- VectorIterator<uc16> ib(content.ToUC16Vector());
- return CompareStringContents(ia, &ib);
+template<typename Chars1, typename Chars2>
+class RawStringComparator : public AllStatic {
+ public:
+ static inline bool compare(const Chars1* a, const Chars2* b, int len) {
+ ASSERT(sizeof(Chars1) != sizeof(Chars2));
+ for (int i = 0; i < len; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
}
- } else {
- isolate->objects_string_compare_buffer_b()->Reset(0, b);
- return CompareStringContents(ia,
- isolate->objects_string_compare_buffer_b());
+ return true;
}
-}
+};
+
+
+template<>
+class RawStringComparator<uint16_t, uint16_t> {
+ public:
+ static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
+ return CompareRawStringContents(a, b, len);
+ }
+};
+
+
+template<>
+class RawStringComparator<uint8_t, uint8_t> {
+ public:
+ static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
+ return CompareRawStringContents(a, b, len);
+ }
+};
+
+
+class StringComparator {
+ class State {
+ public:
+ explicit inline State(ConsStringIteratorOp* op)
+ : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
+
+ inline void Init(String* string, unsigned len) {
+ op_->Reset();
+ int32_t type = string->map()->instance_type();
+ String::Visit(string, 0, *this, *op_, type, len);
+ }
+
+ inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
+ is_one_byte_ = true;
+ buffer8_ = chars;
+ length_ = length;
+ }
+
+ inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
+ is_one_byte_ = false;
+ buffer16_ = chars;
+ length_ = length;
+ }
+
+ void Advance(unsigned consumed) {
+ ASSERT(consumed <= length_);
+ // Still in buffer.
+ if (length_ != consumed) {
+ if (is_one_byte_) {
+ buffer8_ += consumed;
+ } else {
+ buffer16_ += consumed;
+ }
+ length_ -= consumed;
+ return;
+ }
+ // Advance state.
+ ASSERT(op_->HasMore());
+ int32_t type = 0;
+ unsigned length = 0;
+ String* next = op_->ContinueOperation(&type, &length);
+ ASSERT(next != NULL);
+ ConsStringNullOp null_op;
+ String::Visit(next, 0, *this, null_op, type, length);
+ }
+
+ ConsStringIteratorOp* const op_;
+ bool is_one_byte_;
+ unsigned length_;
+ union {
+ const uint8_t* buffer8_;
+ const uint16_t* buffer16_;
+ };
+ DISALLOW_IMPLICIT_CONSTRUCTORS(State);
+ };
+
+ public:
+ inline StringComparator(ConsStringIteratorOp* op_1,
+ ConsStringIteratorOp* op_2)
+ : state_1_(op_1),
+ state_2_(op_2) {
+ }
+
+ template<typename Chars1, typename Chars2>
+ static inline bool Equals(State* state_1, State* state_2, unsigned to_check) {
+ const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
+ const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
+ return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
+ }
+
+ bool Equals(unsigned length, String* string_1, String* string_2) {
+ ASSERT(length != 0);
+ state_1_.Init(string_1, length);
+ state_2_.Init(string_2, length);
+ while (true) {
+ unsigned to_check = Min(state_1_.length_, state_2_.length_);
+ ASSERT(to_check > 0 && to_check <= length);
+ bool is_equal;
+ if (state_1_.is_one_byte_) {
+ if (state_2_.is_one_byte_) {
+ is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
+ } else {
+ is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
+ }
+ } else {
+ if (state_2_.is_one_byte_) {
+ is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
+ } else {
+ is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
+ }
+ }
+ // Looping done.
+ if (!is_equal) return false;
+ length -= to_check;
+ // Exit condition. Strings are equal.
+ if (length == 0) return true;
+ state_1_.Advance(to_check);
+ state_2_.Advance(to_check);
+ }
+ }
+
+ private:
+ State state_1_;
+ State state_2_;
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
+};
bool String::SlowEquals(String* other) {
@@ -7568,58 +7670,19 @@ bool String::SlowEquals(String* other) {
String* lhs = this->TryFlattenGetString();
String* rhs = other->TryFlattenGetString();
+ // TODO(dcarney): Compare all types of flat strings with a Visitor.
if (StringShape(lhs).IsSequentialAscii() &&
StringShape(rhs).IsSequentialAscii()) {
const char* str1 = SeqOneByteString::cast(lhs)->GetChars();
const char* str2 = SeqOneByteString::cast(rhs)->GetChars();
- return CompareRawStringContents(Vector<const char>(str1, len),
- Vector<const char>(str2, len));
+ return CompareRawStringContents(str1, str2, len);
}
Isolate* isolate = GetIsolate();
- String::FlatContent lhs_content = lhs->GetFlatContent();
- String::FlatContent rhs_content = rhs->GetFlatContent();
- if (lhs_content.IsFlat()) {
- if (lhs_content.IsAscii()) {
- Vector<const char> vec1 = lhs_content.ToAsciiVector();
- if (rhs_content.IsFlat()) {
- if (rhs_content.IsAscii()) {
- Vector<const char> vec2 = rhs_content.ToAsciiVector();
- return CompareRawStringContents(vec1, vec2);
- } else {
- VectorIterator<char> buf1(vec1);
- VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
- return CompareStringContents(&buf1, &ib);
- }
- } else {
- VectorIterator<char> buf1(vec1);
- isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
- return CompareStringContents(&buf1,
- isolate->objects_string_compare_buffer_b());
- }
- } else {
- Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
- if (rhs_content.IsFlat()) {
- if (rhs_content.IsAscii()) {
- VectorIterator<uc16> buf1(vec1);
- VectorIterator<char> ib(rhs_content.ToAsciiVector());
- return CompareStringContents(&buf1, &ib);
- } else {
- Vector<const uc16> vec2(rhs_content.ToUC16Vector());
- return CompareRawStringContents(vec1, vec2);
- }
- } else {
- VectorIterator<uc16> buf1(vec1);
- isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
- return CompareStringContents(&buf1,
- isolate->objects_string_compare_buffer_b());
- }
- }
- } else {
- isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
- return CompareStringContentsPartial(isolate,
- isolate->objects_string_compare_buffer_a(), rhs);
- }
+ StringComparator comparator(isolate->objects_string_compare_iterator_a(),
+ isolate->objects_string_compare_iterator_b());
+
+ return comparator.Equals(static_cast<unsigned>(len), lhs, rhs);
}
@@ -7764,11 +7827,12 @@ uint32_t String::ComputeAndSetHash() {
}
-bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
- uint32_t* index,
- int length) {
+bool String::ComputeArrayIndex(uint32_t* index) {
+ int length = this->length();
if (length == 0 || length > kMaxArrayIndexSize) return false;
- uc32 ch = buffer->GetNext();
+ ConsStringIteratorOp op;
+ StringCharacterStream stream(this, &op);
+ uint16_t ch = stream.GetNext();
// If the string begins with a '0' character, it must only consist
// of it to be a legal array index.
@@ -7781,8 +7845,8 @@ bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
int d = ch - '0';
if (d < 0 || d > 9) return false;
uint32_t result = d;
- while (buffer->has_more()) {
- d = buffer->GetNext() - '0';
+ while (stream.HasMore()) {
+ d = stream.GetNext() - '0';
if (d < 0 || d > 9) return false;
// Check that the new result is below the 32 bit limit.
if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
@@ -7803,8 +7867,7 @@ bool String::SlowAsArrayIndex(uint32_t* index) {
*index = (kArrayIndexHashMask & field) >> kHashShift;
return true;
} else {
- StringInputBuffer buffer(this);
- return ComputeArrayIndex(&buffer, index, length());
+ return ComputeArrayIndex(index);
}
}
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698