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,93 +3130,57 @@ String* String::GetUnderlying() { ...@@ -3130,93 +3130,57 @@ 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;
}
}
}
// 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; 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_;
} }
...@@ -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);
......
This diff is collapsed.
...@@ -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