Index: src/objects-inl.h |
diff --git a/src/objects-inl.h b/src/objects-inl.h |
index b99ba44723122cbd4b38fa9e1cdd1b070c7710d9..f633a5c54d71ae6ba81c80b0164936482d9b6613 100644 |
--- a/src/objects-inl.h |
+++ b/src/objects-inl.h |
@@ -2512,6 +2512,79 @@ String* String::GetUnderlying() { |
} |
+template<class Visitor, class ConsOp> |
+void String::Visit( |
+ String* string, |
+ unsigned offset, |
+ Visitor& visitor, |
+ ConsOp& consOp, |
+ int32_t type, |
+ unsigned length) { |
+ |
+ ASSERT(length == static_cast<unsigned>(string->length())); |
+ ASSERT(offset <= length); |
+ |
+ unsigned sliceOffset = offset; |
+ while (true) { |
+ ASSERT(type == string->map()->instance_type()); |
+ |
+ switch (type & (kStringRepresentationMask | kStringEncodingMask)) { |
+ case kSeqStringTag | kOneByteStringTag: |
Yang
2012/12/04 14:49:11
We usually indent switch-case-clauses like
switch
|
+ visitor.VisitOneByteString( |
+ reinterpret_cast<const uint8_t*>( |
+ SeqOneByteString::cast(string)->GetChars()) + sliceOffset, |
+ length - offset); |
Yang
2012/12/04 14:49:11
I suggest adding four more spaces as indentation.
|
+ return; |
+ |
+ case kSeqStringTag | kTwoByteStringTag: |
+ visitor.VisitTwoByteString( |
+ reinterpret_cast<const uint16_t*>( |
+ SeqTwoByteString::cast(string)->GetChars()) + sliceOffset, |
+ length - offset); |
+ return; |
+ |
+ case kExternalStringTag | kOneByteStringTag: |
+ visitor.VisitOneByteString( |
+ reinterpret_cast<const uint8_t*>( |
+ ExternalAsciiString::cast(string)->GetChars()) + sliceOffset, |
+ length - offset); |
+ return; |
+ |
+ case kExternalStringTag | kTwoByteStringTag: |
+ visitor.VisitTwoByteString( |
+ reinterpret_cast<const uint16_t*>( |
+ ExternalTwoByteString::cast(string)->GetChars()) + sliceOffset, |
+ length - offset); |
+ return; |
+ |
+ case kSlicedStringTag | kOneByteStringTag: |
+ case kSlicedStringTag | kTwoByteStringTag: |
+ { |
+ SlicedString* slicedString = SlicedString::cast(string); |
+ sliceOffset += slicedString->offset(); |
+ string = slicedString->parent(); |
+ type = string->map()->instance_type(); |
+ continue; |
+ } |
+ |
+ case kConsStringTag | kOneByteStringTag: |
+ case kConsStringTag | kTwoByteStringTag: |
+ string = consOp.Operate( |
+ ConsString::cast(string), &offset, &type, &length); |
+ if (string == NULL) |
Yang
2012/12/04 14:49:11
no line break here.
|
+ return; |
+ sliceOffset = offset; |
+ ASSERT(length == static_cast<unsigned>(string->length())); |
+ continue; |
+ |
+ default: |
+ UNREACHABLE(); |
+ return; |
+ } |
+ } |
+} |
+ |
+ |
uint16_t SeqOneByteString::SeqOneByteStringGet(int index) { |
ASSERT(index >= 0 && index < length()); |
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); |
@@ -2690,6 +2763,149 @@ const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData( |
} |
+unsigned ConsStringIteratorOp::OffsetForDepth(unsigned depth) { |
+ return depth & depthMask; |
+} |
+ |
+ |
+uint32_t ConsStringIteratorOp::MaskForDepth(unsigned depth) { |
+ return 1 << OffsetForDepth(depth); |
+} |
+ |
+ |
+void ConsStringIteratorOp::SetRightDescent() { |
+ trace |= MaskForDepth(depth - 1); |
+} |
+ |
+ |
+void ConsStringIteratorOp::ClearRightDescent() { |
+ trace &= ~MaskForDepth(depth - 1); |
+} |
+ |
+ |
+void ConsStringIteratorOp::PushLeft(ConsString* string) { |
+ frames[depth++ & depthMask] = string; |
+} |
+ |
+ |
+void ConsStringIteratorOp::PushRight(ConsString* string, int32_t type) { |
+ // Inplace update |
+ frames[depth-1 & depthMask] = string; |
+ // Optimization: can replace root here. |
+ if (depth == 1) { |
+ root = string; |
+ rootType = type; |
+ rootLength = root->length(); |
+ } |
+} |
+ |
+ |
+void ConsStringIteratorOp::AdjustMaximumDepth() { |
+ if (depth > maximumDepth) |
+ maximumDepth = depth; |
Yang
2012/12/04 14:49:11
No line break here.
|
+} |
+ |
+ |
+void ConsStringIteratorOp::Pop() { |
+ ASSERT(depth > 0); |
+ ASSERT(depth <= maximumDepth); |
+ depth--; |
+} |
+ |
+ |
+void ConsStringIteratorOp::Reset() { |
+ consumed = 0; |
+ ResetStack(); |
+} |
+ |
+ |
+bool ConsStringIteratorOp::HasMore() { |
+ return depth != 0; |
+} |
+ |
+ |
+void ConsStringIteratorOp::ResetStack() { |
+ depth = 0; |
+ maximumDepth = 0; |
+} |
+ |
+ |
+bool ConsStringIteratorOp::ContinueOperation(ContinueResponse* response) { |
+ bool blewStack; |
+ int32_t type; |
+ String* string = NextLeaf(&blewStack, &type); |
+ // String found. |
+ if (string != NULL) { |
+ unsigned length = string->length(); |
+ consumed += length; |
+ response->string = string; |
+ response->offset = 0; |
+ response->length = length; |
+ response->type = type; |
+ return true; |
+ } |
+ // Traversal complete. |
+ if (!blewStack) |
+ return false; |
Yang
2012/12/04 14:49:11
no line break.
|
+ // Restart search. |
+ ResetStack(); |
+ response->string = root; |
+ response->offset = consumed; |
+ response->length = root->length(); |
+ response->type = rootType; |
+ return true; |
+} |
+ |
+ |
+uint16_t StringBufferStream::GetNext() { |
+ return isOneByte ? *buffer8++ : *buffer16++; |
+} |
+ |
+ |
+void StringBufferStream::Reset(String* string, unsigned offset, |
Yang
2012/12/04 14:49:11
Please put all arguments on the second line.
|
+ ConsStringIteratorOp* op) { |
+ buffer8 = NULL; |
+ end = NULL; |
+ this->op = op; |
+ op->Reset(); |
+ String::Visit(string, |
+ offset, *this, *op, string->map()->instance_type(), string->length()); |
+} |
+ |
+ |
+bool StringBufferStream::has_more() { |
+ if (buffer8 != end) |
+ return true; |
Yang
2012/12/04 14:49:11
no line break here and in the following if.
|
+ if (!op->HasMore()) |
+ return false; |
+ ConsStringIteratorOp::ContinueResponse response; |
+ // This has been checked above |
+ if (!op->ContinueOperation(&response)) { |
+ UNREACHABLE(); |
+ return false; |
+ } |
+ String::Visit(response.string, |
+ response.offset, *this, *op, response.type, response.length); |
+ return true; |
+} |
+ |
+ |
+void StringBufferStream::VisitOneByteString(const uint8_t* chars, |
+ unsigned length) { |
Yang
2012/12/04 14:49:11
Either align the two arguments or put both on the
|
+ isOneByte = true; |
+ buffer8 = chars; |
+ end = chars + length; |
+} |
+ |
+ |
+void StringBufferStream::VisitTwoByteString(const uint16_t* chars, |
+ unsigned length) { |
Yang
2012/12/04 14:49:11
Ditto.
|
+ isOneByte = false; |
+ buffer16 = chars; |
+ end = reinterpret_cast<const uint8_t*>(chars + length); |
+} |
+ |
+ |
void JSFunctionResultCache::MakeZeroSize() { |
set_finger_index(kEntriesIndex); |
set_size(kEntriesIndex); |