Commit 7b1e8304 authored by dcarney@chromium.org's avatar dcarney@chromium.org

Remove String::Visit

R=yangguo@chromium.org

BUG=

Review URL: https://codereview.chromium.org/254763008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21046 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f9fa6194
...@@ -3130,96 +3130,60 @@ String* String::GetUnderlying() { ...@@ -3130,96 +3130,60 @@ String* String::GetUnderlying() {
} }
template<class Visitor, class ConsOp> template<class Visitor>
void String::Visit( ConsString* String::VisitFlat(Visitor* visitor,
String* string, String* string,
unsigned offset, const int offset) {
Visitor& visitor, int slice_offset = offset;
ConsOp& cons_op, const int length = string->length();
int32_t type,
unsigned length) {
ASSERT(length == static_cast<unsigned>(string->length()));
ASSERT(offset <= length); ASSERT(offset <= length);
unsigned slice_offset = offset;
while (true) { while (true) {
ASSERT(type == string->map()->instance_type()); int32_t type = string->map()->instance_type();
switch (type & (kStringRepresentationMask | kStringEncodingMask)) { switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
case kSeqStringTag | kOneByteStringTag: case kSeqStringTag | kOneByteStringTag:
visitor.VisitOneByteString( visitor->VisitOneByteString(
SeqOneByteString::cast(string)->GetChars() + slice_offset, SeqOneByteString::cast(string)->GetChars() + slice_offset,
length - offset); length - offset);
return; return NULL;
case kSeqStringTag | kTwoByteStringTag: case kSeqStringTag | kTwoByteStringTag:
visitor.VisitTwoByteString( visitor->VisitTwoByteString(
SeqTwoByteString::cast(string)->GetChars() + slice_offset, SeqTwoByteString::cast(string)->GetChars() + slice_offset,
length - offset); length - offset);
return; return NULL;
case kExternalStringTag | kOneByteStringTag: case kExternalStringTag | kOneByteStringTag:
visitor.VisitOneByteString( visitor->VisitOneByteString(
ExternalAsciiString::cast(string)->GetChars() + slice_offset, ExternalAsciiString::cast(string)->GetChars() + slice_offset,
length - offset); length - offset);
return; return NULL;
case kExternalStringTag | kTwoByteStringTag: case kExternalStringTag | kTwoByteStringTag:
visitor.VisitTwoByteString( visitor->VisitTwoByteString(
ExternalTwoByteString::cast(string)->GetChars() + slice_offset, ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
length - offset); length - offset);
return; return NULL;
case kSlicedStringTag | kOneByteStringTag: case kSlicedStringTag | kOneByteStringTag:
case kSlicedStringTag | kTwoByteStringTag: { case kSlicedStringTag | kTwoByteStringTag: {
SlicedString* slicedString = SlicedString::cast(string); SlicedString* slicedString = SlicedString::cast(string);
slice_offset += slicedString->offset(); slice_offset += slicedString->offset();
string = slicedString->parent(); string = slicedString->parent();
type = string->map()->instance_type();
continue; continue;
} }
case kConsStringTag | kOneByteStringTag: case kConsStringTag | kOneByteStringTag:
case kConsStringTag | kTwoByteStringTag: case kConsStringTag | kTwoByteStringTag:
string = cons_op.Operate(string, &offset, &type, &length); return ConsString::cast(string);
if (string == NULL) return;
slice_offset = offset;
ASSERT(length == static_cast<unsigned>(string->length()));
continue;
default: default:
UNREACHABLE(); UNREACHABLE();
return; return NULL;
} }
} }
} }
// TODO(dcarney): Remove this class after conversion to VisitFlat.
class ConsStringCaptureOp {
public:
inline ConsStringCaptureOp() : cons_string_(NULL) {}
inline String* Operate(String* string, unsigned*, int32_t*, unsigned*) {
cons_string_ = ConsString::cast(string);
return NULL;
}
ConsString* cons_string_;
};
template<class Visitor>
ConsString* String::VisitFlat(Visitor* visitor,
String* string,
int offset,
int length,
int32_t type) {
ASSERT(length >= 0 && length == string->length());
ASSERT(offset >= 0 && offset <= length);
ConsStringCaptureOp op;
Visit(string, offset, *visitor, op, type, static_cast<unsigned>(length));
return op.cons_string_;
}
uint16_t SeqOneByteString::SeqOneByteStringGet(int index) { uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
ASSERT(index >= 0 && index < length()); ASSERT(index >= 0 && index < length());
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
...@@ -3399,12 +3363,7 @@ const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData( ...@@ -3399,12 +3363,7 @@ const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
} }
String* ConsStringNullOp::Operate(String*, unsigned*, int32_t*, unsigned*) { int ConsStringIteratorOp::OffsetForDepth(int depth) {
return NULL;
}
unsigned ConsStringIteratorOp::OffsetForDepth(unsigned depth) {
return depth & kDepthMask; return depth & kDepthMask;
} }
...@@ -3432,45 +3391,9 @@ void ConsStringIteratorOp::Pop() { ...@@ -3432,45 +3391,9 @@ void ConsStringIteratorOp::Pop() {
} }
bool ConsStringIteratorOp::HasMore() {
return depth_ != 0;
}
void ConsStringIteratorOp::Reset() {
depth_ = 0;
}
String* ConsStringIteratorOp::ContinueOperation(int32_t* type_out,
unsigned* length_out) {
bool blew_stack = false;
String* string = NextLeaf(&blew_stack, type_out, length_out);
// String found.
if (string != NULL) {
// Verify output.
ASSERT(*length_out == static_cast<unsigned>(string->length()));
ASSERT(*type_out == string->map()->instance_type());
return string;
}
// Traversal complete.
if (!blew_stack) return NULL;
// Restart search from root.
unsigned offset_out;
string = Search(&offset_out, type_out, length_out);
// Verify output.
ASSERT(string == NULL || offset_out == 0);
ASSERT(string == NULL ||
*length_out == static_cast<unsigned>(string->length()));
ASSERT(string == NULL || *type_out == string->map()->instance_type());
return string;
}
uint16_t StringCharacterStream::GetNext() { uint16_t StringCharacterStream::GetNext() {
ASSERT(buffer8_ != NULL && end_ != NULL); ASSERT(buffer8_ != NULL && end_ != NULL);
// Advance cursor if needed. // Advance cursor if needed.
// TODO(dcarney): Ensure uses of the api call HasMore first and avoid this.
if (buffer8_ == end_) HasMore(); if (buffer8_ == end_) HasMore();
ASSERT(buffer8_ < end_); ASSERT(buffer8_ < end_);
return is_one_byte_ ? *buffer8_++ : *buffer16_++; return is_one_byte_ ? *buffer8_++ : *buffer16_++;
...@@ -3479,41 +3402,39 @@ uint16_t StringCharacterStream::GetNext() { ...@@ -3479,41 +3402,39 @@ uint16_t StringCharacterStream::GetNext() {
StringCharacterStream::StringCharacterStream(String* string, StringCharacterStream::StringCharacterStream(String* string,
ConsStringIteratorOp* op, ConsStringIteratorOp* op,
unsigned offset) int offset)
: is_one_byte_(false), : is_one_byte_(false),
op_(op) { op_(op) {
Reset(string, offset); Reset(string, offset);
} }
void StringCharacterStream::Reset(String* string, unsigned offset) { void StringCharacterStream::Reset(String* string, int offset) {
op_->Reset();
buffer8_ = NULL; buffer8_ = NULL;
end_ = NULL; end_ = NULL;
int32_t type = string->map()->instance_type(); ConsString* cons_string = String::VisitFlat(this, string, offset);
unsigned length = string->length(); op_->Reset(cons_string, offset);
String::Visit(string, offset, *this, *op_, type, length); if (cons_string != NULL) {
string = op_->Next(&offset);
if (string != NULL) String::VisitFlat(this, string, offset);
}
} }
bool StringCharacterStream::HasMore() { bool StringCharacterStream::HasMore() {
if (buffer8_ != end_) return true; if (buffer8_ != end_) return true;
if (!op_->HasMore()) return false; int offset;
unsigned length; String* string = op_->Next(&offset);
int32_t type; ASSERT_EQ(offset, 0);
String* string = op_->ContinueOperation(&type, &length);
if (string == NULL) return false; if (string == NULL) return false;
ASSERT(!string->IsConsString()); String::VisitFlat(this, string);
ASSERT(string->length() != 0);
ConsStringNullOp null_op;
String::Visit(string, 0, *this, null_op, type, length);
ASSERT(buffer8_ != end_); ASSERT(buffer8_ != end_);
return true; return true;
} }
void StringCharacterStream::VisitOneByteString( void StringCharacterStream::VisitOneByteString(
const uint8_t* chars, unsigned length) { const uint8_t* chars, int length) {
is_one_byte_ = true; is_one_byte_ = true;
buffer8_ = chars; buffer8_ = chars;
end_ = chars + length; end_ = chars + length;
...@@ -3521,7 +3442,7 @@ void StringCharacterStream::VisitOneByteString( ...@@ -3521,7 +3442,7 @@ void StringCharacterStream::VisitOneByteString(
void StringCharacterStream::VisitTwoByteString( void StringCharacterStream::VisitTwoByteString(
const uint16_t* chars, unsigned length) { const uint16_t* chars, int length) {
is_one_byte_ = false; is_one_byte_ = false;
buffer16_ = chars; buffer16_ = chars;
end_ = reinterpret_cast<const uint8_t*>(chars + length); end_ = reinterpret_cast<const uint8_t*>(chars + length);
......
...@@ -8826,34 +8826,47 @@ void FlatStringReader::PostGarbageCollection() { ...@@ -8826,34 +8826,47 @@ void FlatStringReader::PostGarbageCollection() {
} }
String* ConsStringIteratorOp::Operate(String* string, void ConsStringIteratorOp::Initialize(ConsString* cons_string, int offset) {
unsigned* offset_out, ASSERT(cons_string != NULL);
int32_t* type_out,
unsigned* length_out) {
ASSERT(string->IsConsString());
ConsString* cons_string = ConsString::cast(string);
// Set up search data.
root_ = cons_string; root_ = cons_string;
consumed_ = *offset_out; consumed_ = offset;
// Now search. // Force stack blown condition to trigger restart.
return Search(offset_out, type_out, length_out); depth_ = 1;
maximum_depth_ = kStackSize + depth_;
ASSERT(StackBlown());
} }
String* ConsStringIteratorOp::Search(unsigned* offset_out, String* ConsStringIteratorOp::Continue(int* offset_out) {
int32_t* type_out, ASSERT(depth_ != 0);
unsigned* length_out) { ASSERT_EQ(0, *offset_out);
bool blew_stack = StackBlown();
String* string = NULL;
// Get the next leaf if there is one.
if (!blew_stack) string = NextLeaf(&blew_stack);
// Restart search from root.
if (blew_stack) {
ASSERT(string == NULL);
string = Search(offset_out);
}
// Ensure future calls return null immediately.
if (string == NULL) Reset(NULL);
return string;
}
String* ConsStringIteratorOp::Search(int* offset_out) {
ConsString* cons_string = root_; ConsString* cons_string = root_;
// Reset the stack, pushing the root string. // Reset the stack, pushing the root string.
depth_ = 1; depth_ = 1;
maximum_depth_ = 1; maximum_depth_ = 1;
frames_[0] = cons_string; frames_[0] = cons_string;
const unsigned consumed = consumed_; const int consumed = consumed_;
unsigned offset = 0; int offset = 0;
while (true) { while (true) {
// Loop until the string is found which contains the target offset. // Loop until the string is found which contains the target offset.
String* string = cons_string->first(); String* string = cons_string->first();
unsigned length = string->length(); int length = string->length();
int32_t type; int32_t type;
if (consumed < offset + length) { if (consumed < offset + length) {
// Target offset is in the left branch. // Target offset is in the left branch.
...@@ -8864,7 +8877,7 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out, ...@@ -8864,7 +8877,7 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out,
PushLeft(cons_string); PushLeft(cons_string);
continue; continue;
} }
// Tell the stack we're done decending. // Tell the stack we're done descending.
AdjustMaximumDepth(); AdjustMaximumDepth();
} else { } else {
// Descend right. // Descend right.
...@@ -8876,7 +8889,6 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out, ...@@ -8876,7 +8889,6 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out,
if ((type & kStringRepresentationMask) == kConsStringTag) { if ((type & kStringRepresentationMask) == kConsStringTag) {
cons_string = ConsString::cast(string); cons_string = ConsString::cast(string);
PushRight(cons_string); PushRight(cons_string);
// TODO(dcarney) Add back root optimization.
continue; continue;
} }
// Need this to be updated for the current string. // Need this to be updated for the current string.
...@@ -8884,11 +8896,11 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out, ...@@ -8884,11 +8896,11 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out,
// Account for the possibility of an empty right leaf. // Account for the possibility of an empty right leaf.
// This happens only if we have asked for an offset outside the string. // This happens only if we have asked for an offset outside the string.
if (length == 0) { if (length == 0) {
// Reset depth so future operations will return null immediately. // Reset so future operations will return null immediately.
Reset(); Reset(NULL);
return NULL; return NULL;
} }
// Tell the stack we're done decending. // Tell the stack we're done descending.
AdjustMaximumDepth(); AdjustMaximumDepth();
// Pop stack so next iteration is in correct place. // Pop stack so next iteration is in correct place.
Pop(); Pop();
...@@ -8897,8 +8909,6 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out, ...@@ -8897,8 +8909,6 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out,
// Adjust return values and exit. // Adjust return values and exit.
consumed_ = offset + length; consumed_ = offset + length;
*offset_out = consumed - offset; *offset_out = consumed - offset;
*type_out = type;
*length_out = length;
return string; return string;
} }
UNREACHABLE(); UNREACHABLE();
...@@ -8906,9 +8916,7 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out, ...@@ -8906,9 +8916,7 @@ String* ConsStringIteratorOp::Search(unsigned* offset_out,
} }
String* ConsStringIteratorOp::NextLeaf(bool* blew_stack, String* ConsStringIteratorOp::NextLeaf(bool* blew_stack) {
int32_t* type_out,
unsigned* length_out) {
while (true) { while (true) {
// Tree traversal complete. // Tree traversal complete.
if (depth_ == 0) { if (depth_ == 0) {
...@@ -8916,7 +8924,7 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack, ...@@ -8916,7 +8924,7 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
return NULL; return NULL;
} }
// We've lost track of higher nodes. // We've lost track of higher nodes.
if (maximum_depth_ - depth_ == kStackSize) { if (StackBlown()) {
*blew_stack = true; *blew_stack = true;
return NULL; return NULL;
} }
...@@ -8927,16 +8935,13 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack, ...@@ -8927,16 +8935,13 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
if ((type & kStringRepresentationMask) != kConsStringTag) { if ((type & kStringRepresentationMask) != kConsStringTag) {
// Pop stack so next iteration is in correct place. // Pop stack so next iteration is in correct place.
Pop(); Pop();
unsigned length = static_cast<unsigned>(string->length()); int length = string->length();
// Could be a flattened ConsString. // Could be a flattened ConsString.
if (length == 0) continue; if (length == 0) continue;
*length_out = length;
*type_out = type;
consumed_ += length; consumed_ += length;
return string; return string;
} }
cons_string = ConsString::cast(string); cons_string = ConsString::cast(string);
// TODO(dcarney) Add back root optimization.
PushRight(cons_string); PushRight(cons_string);
// Need to traverse all the way left. // Need to traverse all the way left.
while (true) { while (true) {
...@@ -8945,10 +8950,8 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack, ...@@ -8945,10 +8950,8 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
type = string->map()->instance_type(); type = string->map()->instance_type();
if ((type & kStringRepresentationMask) != kConsStringTag) { if ((type & kStringRepresentationMask) != kConsStringTag) {
AdjustMaximumDepth(); AdjustMaximumDepth();
unsigned length = static_cast<unsigned>(string->length()); int length = string->length();
ASSERT(length != 0); ASSERT(length != 0);
*length_out = length;
*type_out = type;
consumed_ += length; consumed_ += length;
return string; return string;
} }
...@@ -9223,25 +9226,29 @@ class StringComparator { ...@@ -9223,25 +9226,29 @@ class StringComparator {
explicit inline State(ConsStringIteratorOp* op) explicit inline State(ConsStringIteratorOp* op)
: op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {} : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
inline void Init(String* string, unsigned len) { inline void Init(String* string) {
op_->Reset(); ConsString* cons_string = String::VisitFlat(this, string);
int32_t type = string->map()->instance_type(); op_->Reset(cons_string);
String::Visit(string, 0, *this, *op_, type, len); if (cons_string != NULL) {
int offset;
string = op_->Next(&offset);
String::VisitFlat(this, string, offset);
}
} }
inline void VisitOneByteString(const uint8_t* chars, unsigned length) { inline void VisitOneByteString(const uint8_t* chars, int length) {
is_one_byte_ = true; is_one_byte_ = true;
buffer8_ = chars; buffer8_ = chars;
length_ = length; length_ = length;
} }
inline void VisitTwoByteString(const uint16_t* chars, unsigned length) { inline void VisitTwoByteString(const uint16_t* chars, int length) {
is_one_byte_ = false; is_one_byte_ = false;
buffer16_ = chars; buffer16_ = chars;
length_ = length; length_ = length;
} }
void Advance(unsigned consumed) { void Advance(int consumed) {
ASSERT(consumed <= length_); ASSERT(consumed <= length_);
// Still in buffer. // Still in buffer.
if (length_ != consumed) { if (length_ != consumed) {
...@@ -9254,18 +9261,16 @@ class StringComparator { ...@@ -9254,18 +9261,16 @@ class StringComparator {
return; return;
} }
// Advance state. // Advance state.
ASSERT(op_->HasMore()); int offset;
int32_t type = 0; String* next = op_->Next(&offset);
unsigned length = 0; ASSERT_EQ(0, offset);
String* next = op_->ContinueOperation(&type, &length);
ASSERT(next != NULL); ASSERT(next != NULL);
ConsStringNullOp null_op; String::VisitFlat(this, next);
String::Visit(next, 0, *this, null_op, type, length);
} }
ConsStringIteratorOp* const op_; ConsStringIteratorOp* const op_;
bool is_one_byte_; bool is_one_byte_;
unsigned length_; int length_;
union { union {
const uint8_t* buffer8_; const uint8_t* buffer8_;
const uint16_t* buffer16_; const uint16_t* buffer16_;
...@@ -9283,18 +9288,18 @@ class StringComparator { ...@@ -9283,18 +9288,18 @@ class StringComparator {
} }
template<typename Chars1, typename Chars2> template<typename Chars1, typename Chars2>
static inline bool Equals(State* state_1, State* state_2, unsigned to_check) { static inline bool Equals(State* state_1, State* state_2, int to_check) {
const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_); const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_); const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check); return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
} }
bool Equals(unsigned length, String* string_1, String* string_2) { bool Equals(String* string_1, String* string_2) {
ASSERT(length != 0); int length = string_1->length();
state_1_.Init(string_1, length); state_1_.Init(string_1);
state_2_.Init(string_2, length); state_2_.Init(string_2);
while (true) { while (true) {
unsigned to_check = Min(state_1_.length_, state_2_.length_); int to_check = Min(state_1_.length_, state_2_.length_);
ASSERT(to_check > 0 && to_check <= length); ASSERT(to_check > 0 && to_check <= length);
bool is_equal; bool is_equal;
if (state_1_.is_one_byte_) { if (state_1_.is_one_byte_) {
...@@ -9358,7 +9363,6 @@ bool String::SlowEquals(String* other) { ...@@ -9358,7 +9363,6 @@ bool String::SlowEquals(String* other) {
// before we try to flatten the strings. // before we try to flatten the strings.
if (this->Get(0) != other->Get(0)) return false; if (this->Get(0) != other->Get(0)) return false;
// TODO(dcarney): Compare all types of flat strings with a Visitor.
if (IsSeqOneByteString() && other->IsSeqOneByteString()) { if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars(); const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars(); const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
...@@ -9369,7 +9373,7 @@ bool String::SlowEquals(String* other) { ...@@ -9369,7 +9373,7 @@ bool String::SlowEquals(String* other) {
StringComparator comparator(isolate->objects_string_compare_iterator_a(), StringComparator comparator(isolate->objects_string_compare_iterator_a(),
isolate->objects_string_compare_iterator_b()); isolate->objects_string_compare_iterator_b());
return comparator.Equals(static_cast<unsigned>(len), this, other); return comparator.Equals(this, other);
} }
...@@ -9504,49 +9508,31 @@ bool String::IsTwoByteEqualTo(Vector<const uc16> str) { ...@@ -9504,49 +9508,31 @@ bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
class IteratingStringHasher: public StringHasher { class IteratingStringHasher: public StringHasher {
public: public:
static inline uint32_t Hash(String* string, uint32_t seed) { static inline uint32_t Hash(String* string, uint32_t seed) {
const unsigned len = static_cast<unsigned>(string->length()); IteratingStringHasher hasher(string->length(), seed);
IteratingStringHasher hasher(len, seed); // Nothing to do.
if (hasher.has_trivial_hash()) { if (hasher.has_trivial_hash()) return hasher.GetHashField();
return hasher.GetHashField(); ConsString* cons_string = String::VisitFlat(&hasher, string);
} // The string was flat.
int32_t type = string->map()->instance_type(); if (cons_string == NULL) return hasher.GetHashField();
ConsStringNullOp null_op;
String::Visit(string, 0, hasher, null_op, type, len);
// Flat strings terminate immediately.
if (hasher.consumed_ == len) {
ASSERT(!string->IsConsString());
return hasher.GetHashField();
}
ASSERT(string->IsConsString());
// This is a ConsString, iterate across it. // This is a ConsString, iterate across it.
ConsStringIteratorOp op; ConsStringIteratorOp op(cons_string);
unsigned offset = 0; int offset;
unsigned leaf_length = len; while (NULL != (string = op.Next(&offset))) {
string = op.Operate(string, &offset, &type, &leaf_length); String::VisitFlat(&hasher, string, offset);
while (true) {
ASSERT(hasher.consumed_ < len);
String::Visit(string, 0, hasher, null_op, type, leaf_length);
if (hasher.consumed_ == len) break;
string = op.ContinueOperation(&type, &leaf_length);
// This should be taken care of by the length check.
ASSERT(string != NULL);
} }
return hasher.GetHashField(); return hasher.GetHashField();
} }
inline void VisitOneByteString(const uint8_t* chars, unsigned length) { inline void VisitOneByteString(const uint8_t* chars, int length) {
AddCharacters(chars, static_cast<int>(length)); AddCharacters(chars, length);
consumed_ += length;
} }
inline void VisitTwoByteString(const uint16_t* chars, unsigned length) { inline void VisitTwoByteString(const uint16_t* chars, int length) {
AddCharacters(chars, static_cast<int>(length)); AddCharacters(chars, length);
consumed_ += length;
} }
private: private:
inline IteratingStringHasher(int len, uint32_t seed) inline IteratingStringHasher(int len, uint32_t seed)
: StringHasher(len, seed), : StringHasher(len, seed) {
consumed_(0) {} }
unsigned consumed_;
DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher); DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
}; };
......
...@@ -9209,29 +9209,10 @@ class String: public Name { ...@@ -9209,29 +9209,10 @@ class String: public Name {
return NonOneByteStart(chars, length) >= length; return NonOneByteStart(chars, length) >= length;
} }
// TODO(dcarney): Replace all instances of this with VisitFlat.
template<class Visitor, class ConsOp>
static inline void Visit(String* string,
unsigned offset,
Visitor& visitor,
ConsOp& cons_op,
int32_t type,
unsigned length);
template<class Visitor>
static inline ConsString* VisitFlat(Visitor* visitor,
String* string,
int offset,
int length,
int32_t type);
template<class Visitor> template<class Visitor>
static inline ConsString* VisitFlat(Visitor* visitor, static inline ConsString* VisitFlat(Visitor* visitor,
String* string, String* string,
int offset = 0) { int offset = 0);
int32_t type = string->map()->instance_type();
return VisitFlat(visitor, string, offset, string->length(), type);
}
static Handle<FixedArray> CalculateLineEnds(Handle<String> string, static Handle<FixedArray> CalculateLineEnds(Handle<String> string,
bool include_ending_line); bool include_ending_line);
...@@ -9617,57 +9598,63 @@ class ConsStringNullOp { ...@@ -9617,57 +9598,63 @@ class ConsStringNullOp {
// This maintains an off-stack representation of the stack frames required // This maintains an off-stack representation of the stack frames required
// to traverse a ConsString, allowing an entirely iterative and restartable // to traverse a ConsString, allowing an entirely iterative and restartable
// traversal of the entire string // traversal of the entire string
// Note: this class is not GC-safe.
class ConsStringIteratorOp { class ConsStringIteratorOp {
public: public:
inline ConsStringIteratorOp() {} inline ConsStringIteratorOp() {}
String* Operate(String* string, inline ConsStringIteratorOp(ConsString* cons_string, int offset = 0) {
unsigned* offset_out, Reset(cons_string, offset);
int32_t* type_out, }
unsigned* length_out); inline void Reset(ConsString* cons_string, int offset = 0) {
inline String* ContinueOperation(int32_t* type_out, unsigned* length_out); depth_ = 0;
inline void Reset(); // Next will always return NULL.
inline bool HasMore(); if (cons_string == NULL) return;
Initialize(cons_string, offset);
}
// Returns NULL when complete.
inline String* Next(int* offset_out) {
*offset_out = 0;
if (depth_ == 0) return NULL;
return Continue(offset_out);
}
private: private:
// TODO(dcarney): Templatize this out for different stack sizes. static const int kStackSize = 32;
static const unsigned kStackSize = 32;
// Use a mask instead of doing modulo operations for stack wrapping. // Use a mask instead of doing modulo operations for stack wrapping.
static const unsigned kDepthMask = kStackSize-1; static const int kDepthMask = kStackSize-1;
STATIC_ASSERT(IS_POWER_OF_TWO(kStackSize)); STATIC_ASSERT(IS_POWER_OF_TWO(kStackSize));
static inline unsigned OffsetForDepth(unsigned depth); static inline int OffsetForDepth(int depth);
inline void PushLeft(ConsString* string); inline void PushLeft(ConsString* string);
inline void PushRight(ConsString* string); inline void PushRight(ConsString* string);
inline void AdjustMaximumDepth(); inline void AdjustMaximumDepth();
inline void Pop(); inline void Pop();
String* NextLeaf(bool* blew_stack, int32_t* type_out, unsigned* length_out); inline bool StackBlown() { return maximum_depth_ - depth_ == kStackSize; }
String* Search(unsigned* offset_out, void Initialize(ConsString* cons_string, int offset);
int32_t* type_out, String* Continue(int* offset_out);
unsigned* length_out); String* NextLeaf(bool* blew_stack);
String* Search(int* offset_out);
unsigned depth_;
unsigned maximum_depth_;
// Stack must always contain only frames for which right traversal // Stack must always contain only frames for which right traversal
// has not yet been performed. // has not yet been performed.
ConsString* frames_[kStackSize]; ConsString* frames_[kStackSize];
unsigned consumed_;
ConsString* root_; ConsString* root_;
int depth_;
int maximum_depth_;
int consumed_;
DISALLOW_COPY_AND_ASSIGN(ConsStringIteratorOp); DISALLOW_COPY_AND_ASSIGN(ConsStringIteratorOp);
}; };
// Note: this class is not GC-safe.
class StringCharacterStream { class StringCharacterStream {
public: public:
inline StringCharacterStream(String* string, inline StringCharacterStream(String* string,
ConsStringIteratorOp* op, ConsStringIteratorOp* op,
unsigned offset = 0); int offset = 0);
inline uint16_t GetNext(); inline uint16_t GetNext();
inline bool HasMore(); inline bool HasMore();
inline void Reset(String* string, unsigned offset = 0); inline void Reset(String* string, int offset = 0);
inline void VisitOneByteString(const uint8_t* chars, unsigned length); inline void VisitOneByteString(const uint8_t* chars, int length);
inline void VisitTwoByteString(const uint16_t* chars, unsigned length); inline void VisitTwoByteString(const uint16_t* chars, int length);
private: private:
bool is_one_byte_; bool is_one_byte_;
......
...@@ -230,11 +230,11 @@ class ConsStringStats { ...@@ -230,11 +230,11 @@ class ConsStringStats {
} }
void Reset(); void Reset();
void VerifyEqual(const ConsStringStats& that) const; void VerifyEqual(const ConsStringStats& that) const;
unsigned leaves_; int leaves_;
unsigned empty_leaves_; int empty_leaves_;
unsigned chars_; int chars_;
unsigned left_traversals_; int left_traversals_;
unsigned right_traversals_; int right_traversals_;
private: private:
DISALLOW_COPY_AND_ASSIGN(ConsStringStats); DISALLOW_COPY_AND_ASSIGN(ConsStringStats);
}; };
...@@ -250,11 +250,11 @@ void ConsStringStats::Reset() { ...@@ -250,11 +250,11 @@ void ConsStringStats::Reset() {
void ConsStringStats::VerifyEqual(const ConsStringStats& that) const { void ConsStringStats::VerifyEqual(const ConsStringStats& that) const {
CHECK(this->leaves_ == that.leaves_); CHECK_EQ(this->leaves_, that.leaves_);
CHECK(this->empty_leaves_ == that.empty_leaves_); CHECK_EQ(this->empty_leaves_, that.empty_leaves_);
CHECK(this->chars_ == that.chars_); CHECK_EQ(this->chars_, that.chars_);
CHECK(this->left_traversals_ == that.left_traversals_); CHECK_EQ(this->left_traversals_, that.left_traversals_);
CHECK(this->right_traversals_ == that.right_traversals_); CHECK_EQ(this->right_traversals_, that.right_traversals_);
} }
...@@ -270,14 +270,14 @@ class ConsStringGenerationData { ...@@ -270,14 +270,14 @@ class ConsStringGenerationData {
double leftness_; double leftness_;
double rightness_; double rightness_;
double empty_leaf_threshold_; double empty_leaf_threshold_;
unsigned max_leaves_; int max_leaves_;
// Cached data. // Cached data.
Handle<String> building_blocks_[kNumberOfBuildingBlocks]; Handle<String> building_blocks_[kNumberOfBuildingBlocks];
String* empty_string_; String* empty_string_;
MyRandomNumberGenerator rng_; MyRandomNumberGenerator rng_;
// Stats. // Stats.
ConsStringStats stats_; ConsStringStats stats_;
unsigned early_terminations_; int early_terminations_;
private: private:
DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData); DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData);
}; };
...@@ -356,23 +356,14 @@ void AccumulateStats(Handle<String> cons_string, ConsStringStats* stats) { ...@@ -356,23 +356,14 @@ void AccumulateStats(Handle<String> cons_string, ConsStringStats* stats) {
void AccumulateStatsWithOperator( void AccumulateStatsWithOperator(
ConsString* cons_string, ConsStringStats* stats) { ConsString* cons_string, ConsStringStats* stats) {
unsigned offset = 0; ConsStringIteratorOp op(cons_string);
int32_t type = cons_string->map()->instance_type(); String* string;
unsigned length = static_cast<unsigned>(cons_string->length()); int offset;
ConsStringIteratorOp op; while (NULL != (string = op.Next(&offset))) {
String* string = op.Operate(cons_string, &offset, &type, &length);
CHECK(string != NULL);
while (true) {
ASSERT(!string->IsConsString());
// Accumulate stats. // Accumulate stats.
CHECK_EQ(0, offset);
stats->leaves_++; stats->leaves_++;
stats->chars_ += string->length(); stats->chars_ += string->length();
// Check for completion.
bool keep_going_fast_check = op.HasMore();
string = op.ContinueOperation(&type, &length);
if (string == NULL) return;
// Verify no false positives for fast check.
CHECK(keep_going_fast_check);
} }
} }
...@@ -380,7 +371,7 @@ void AccumulateStatsWithOperator( ...@@ -380,7 +371,7 @@ void AccumulateStatsWithOperator(
void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) { void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) {
// Verify basic data. // Verify basic data.
CHECK(root->IsConsString()); CHECK(root->IsConsString());
CHECK(static_cast<unsigned>(root->length()) == data->stats_.chars_); CHECK_EQ(root->length(), data->stats_.chars_);
// Recursive verify. // Recursive verify.
ConsStringStats stats; ConsStringStats stats;
AccumulateStats(ConsString::cast(*root), &stats); AccumulateStats(ConsString::cast(*root), &stats);
...@@ -625,9 +616,9 @@ static void VerifyCharacterStream( ...@@ -625,9 +616,9 @@ static void VerifyCharacterStream(
// Want to test the offset == length case. // Want to test the offset == length case.
if (offset > length) offset = length; if (offset > length) offset = length;
StringCharacterStream flat_stream( StringCharacterStream flat_stream(
flat_string, &cons_string_iterator_op_1, static_cast<unsigned>(offset)); flat_string, &cons_string_iterator_op_1, offset);
StringCharacterStream cons_stream( StringCharacterStream cons_stream(
cons_string, &cons_string_iterator_op_2, static_cast<unsigned>(offset)); cons_string, &cons_string_iterator_op_2, offset);
for (int i = offset; i < length; i++) { for (int i = offset; i < length; i++) {
uint16_t c = flat_string->Get(i); uint16_t c = flat_string->Get(i);
CHECK(flat_stream.HasMore()); CHECK(flat_stream.HasMore());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment