Chromium Code Reviews| 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); |