Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 405867a908f3f34f91841dbaafac7fa86519f34c..6c44fb96da506468d70b5cd19f861cb3c28e56ad 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -7013,6 +7013,131 @@ void StringInputBuffer::Seek(unsigned pos) { |
| } |
| +String* ConsStringIteratorOp::Operate(ConsString* consString, |
| + unsigned* outerOffset, int32_t* typeOut, unsigned* lengthOut) { |
| + ASSERT(*lengthOut == (unsigned)consString->length()); |
| + // Push the root string. |
| + PushLeft(consString); |
| + root_ = consString; |
| + root_type_ = *typeOut; |
| + root_length_ = *lengthOut; |
| + unsigned targetOffset = *outerOffset; |
| + unsigned offset = 0; |
| + while (true) { |
| + // Loop until the string is found which contains the target offset. |
| + String* string = consString->first(); |
| + unsigned length = string->length(); |
| + int32_t type; |
| + if (targetOffset < offset + length) { |
| + // Target offset is in the left branch. |
| + // Mark the descent. |
| + ClearRightDescent(); |
| + // Keep going if we're still in a ConString. |
| + type = string->map()->instance_type(); |
| + if ((type & kStringRepresentationMask) == kConsStringTag) { |
| + consString = ConsString::cast(string); |
| + PushLeft(consString); |
| + continue; |
| + } |
| + } else { |
| + // Descend right. |
| + // Update progress through the string. |
| + offset += length; |
| + // Keep going if we're still in a ConString. |
| + string = consString->second(); |
| + type = string->map()->instance_type(); |
| + if ((type & kStringRepresentationMask) == kConsStringTag) { |
| + consString = ConsString::cast(string); |
| + PushRight(consString, type); |
| + continue; |
| + } |
| + // Mark the descent. |
| + SetRightDescent(); |
| + // Need this to be updated for the current string. |
| + length = string->length(); |
| + // Account for the possibility of an empty right leaf. |
| + while (length == 0) { |
| + bool blewStack; |
| + // Need to adjust maximum depth for NextLeaf to work. |
| + AdjustMaximumDepth(); |
| + string = NextLeaf(&blewStack, &type); |
| + if (string == NULL) { |
| + // Luckily, this case is impossible. |
| + ASSERT(!blewStack); |
| + return NULL; |
| + } |
| + length = string->length(); |
| + } |
| + } |
| + // Tell the stack we're done decending. |
| + AdjustMaximumDepth(); |
| + ASSERT(length != 0); |
| + // Adjust return values and exit. |
| + unsigned innerOffset = targetOffset - offset; |
| + consumed_ += length - innerOffset; |
| + *outerOffset = innerOffset; |
| + *typeOut = type; |
| + *lengthOut = length; |
| + return string; |
| + } |
| + UNREACHABLE(); |
| + return NULL; |
| +} |
| + |
| + |
| +String* ConsStringIteratorOp::NextLeaf(bool* blewStack, int32_t* typeOut) { |
| + while (true) { |
| + // Tree traversal complete. |
| + if (depth_ == 0) { |
| + *blewStack = false; |
| + return NULL; |
| + } |
| + // We've lost track of higher nodes. |
| + if (maximum_depth_ - depth_ == kStackSize) { |
| + *blewStack = true; |
| + return NULL; |
| + } |
| + // Check if we're done with this level. |
| + bool haveNotReadRight = trace_ & MaskForDepth(depth_ - 1); |
|
Yang
2012/12/06 10:18:47
I'm still somewhat confused about this. Shouldn't
|
| + if (haveNotReadRight) { |
| + Pop(); |
| + continue; |
| + } |
| + // Go right. |
| + ConsString* consString = frames_[OffsetForDepth(depth_ - 1)]; |
| + String* string = consString->second(); |
| + int32_t type = string->map()->instance_type(); |
| + if ((type & kStringRepresentationMask) != kConsStringTag) { |
| + // Don't need to mark the descent here. |
| + // Pop stack so next iteration is in correct place. |
| + Pop(); |
| + *typeOut = type; |
| + return string; |
| + } |
| + // No need to mark the descent. |
| + consString = ConsString::cast(string); |
| + PushRight(consString, type); |
| + // Need to traverse all the way left. |
| + while (true) { |
| + // Continue left. |
| + // Update marker. |
| + ClearRightDescent(); |
| + string = consString->first(); |
| + type = string->map()->instance_type(); |
| + if ((type & kStringRepresentationMask) != kConsStringTag) { |
| + AdjustMaximumDepth(); |
| + *typeOut = type; |
| + return string; |
| + } |
| + consString = ConsString::cast(string); |
| + PushLeft(consString); |
| + } |
| + } |
| + UNREACHABLE(); |
| + return NULL; |
| +} |
| + |
| + |
| // This method determines the type of string involved and then copies |
| // a whole chunk of characters into a buffer. It can be used with strings |
| // that have been glued together to form a ConsString and which must cooperate |