| Index: src/objects.cc
 | 
| diff --git a/src/objects.cc b/src/objects.cc
 | 
| index 20553eb64bc94889c24418fab89dca2eeadf3346..c0c653d509eda4f6d24f6a2ad79fc14894a66b66 100644
 | 
| --- a/src/objects.cc
 | 
| +++ b/src/objects.cc
 | 
| @@ -6693,252 +6693,6 @@ const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
 | 
| -                                                           unsigned* offset_ptr,
 | 
| -                                                           unsigned max_chars) {
 | 
| -  unsigned chars_read = 0;
 | 
| -  unsigned offset = *offset_ptr;
 | 
| -  while (chars_read < max_chars) {
 | 
| -    uint16_t c = *reinterpret_cast<uint16_t*>(
 | 
| -        reinterpret_cast<char*>(this) -
 | 
| -            kHeapObjectTag + kHeaderSize + offset * kShortSize);
 | 
| -    if (c <= kMaxAsciiCharCode) {
 | 
| -      // Fast case for ASCII characters.   Cursor is an input output argument.
 | 
| -      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
 | 
| -                                                          rbb->util_buffer,
 | 
| -                                                          rbb->capacity,
 | 
| -                                                          rbb->cursor)) {
 | 
| -        break;
 | 
| -      }
 | 
| -    } else {
 | 
| -      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
 | 
| -                                                             rbb->util_buffer,
 | 
| -                                                             rbb->capacity,
 | 
| -                                                             rbb->cursor)) {
 | 
| -        break;
 | 
| -      }
 | 
| -    }
 | 
| -    offset++;
 | 
| -    chars_read++;
 | 
| -  }
 | 
| -  *offset_ptr = offset;
 | 
| -  rbb->remaining += chars_read;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -const unibrow::byte* SeqOneByteString::SeqOneByteStringReadBlock(
 | 
| -    unsigned* remaining,
 | 
| -    unsigned* offset_ptr,
 | 
| -    unsigned max_chars) {
 | 
| -  const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
 | 
| -      kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
 | 
| -  *remaining = max_chars;
 | 
| -  *offset_ptr += max_chars;
 | 
| -  return b;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -// This will iterate unless the block of string data spans two 'halves' of
 | 
| -// a ConsString, in which case it will recurse.  Since the block of string
 | 
| -// data to be read has a maximum size this limits the maximum recursion
 | 
| -// depth to something sane.  Since C++ does not have tail call recursion
 | 
| -// elimination, the iteration must be explicit. Since this is not an
 | 
| -// -IntoBuffer method it can delegate to one of the efficient
 | 
| -// *AsciiStringReadBlock routines.
 | 
| -const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
 | 
| -                                                     unsigned* offset_ptr,
 | 
| -                                                     unsigned max_chars) {
 | 
| -  ConsString* current = this;
 | 
| -  unsigned offset = *offset_ptr;
 | 
| -  int offset_correction = 0;
 | 
| -
 | 
| -  while (true) {
 | 
| -    String* left = current->first();
 | 
| -    unsigned left_length = (unsigned)left->length();
 | 
| -    if (left_length > offset &&
 | 
| -        (max_chars <= left_length - offset ||
 | 
| -         (rbb->capacity <= left_length - offset &&
 | 
| -          (max_chars = left_length - offset, true)))) {  // comma operator!
 | 
| -      // Left hand side only - iterate unless we have reached the bottom of
 | 
| -      // the cons tree.  The assignment on the left of the comma operator is
 | 
| -      // in order to make use of the fact that the -IntoBuffer routines can
 | 
| -      // produce at most 'capacity' characters.  This enables us to postpone
 | 
| -      // the point where we switch to the -IntoBuffer routines (below) in order
 | 
| -      // to maximize the chances of delegating a big chunk of work to the
 | 
| -      // efficient *AsciiStringReadBlock routines.
 | 
| -      if (StringShape(left).IsCons()) {
 | 
| -        current = ConsString::cast(left);
 | 
| -        continue;
 | 
| -      } else {
 | 
| -        const unibrow::byte* answer =
 | 
| -            String::ReadBlock(left, rbb, &offset, max_chars);
 | 
| -        *offset_ptr = offset + offset_correction;
 | 
| -        return answer;
 | 
| -      }
 | 
| -    } else if (left_length <= offset) {
 | 
| -      // Right hand side only - iterate unless we have reached the bottom of
 | 
| -      // the cons tree.
 | 
| -      String* right = current->second();
 | 
| -      offset -= left_length;
 | 
| -      offset_correction += left_length;
 | 
| -      if (StringShape(right).IsCons()) {
 | 
| -        current = ConsString::cast(right);
 | 
| -        continue;
 | 
| -      } else {
 | 
| -        const unibrow::byte* answer =
 | 
| -            String::ReadBlock(right, rbb, &offset, max_chars);
 | 
| -        *offset_ptr = offset + offset_correction;
 | 
| -        return answer;
 | 
| -      }
 | 
| -    } else {
 | 
| -      // The block to be read spans two sides of the ConsString, so we call the
 | 
| -      // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
 | 
| -      // are able to assemble data from several part strings because they use
 | 
| -      // the util_buffer to store their data and never return direct pointers
 | 
| -      // to their storage.  We don't try to read more than the buffer capacity
 | 
| -      // here or we can get too much recursion.
 | 
| -      ASSERT(rbb->remaining == 0);
 | 
| -      ASSERT(rbb->cursor == 0);
 | 
| -      current->ConsStringReadBlockIntoBuffer(
 | 
| -          rbb,
 | 
| -          &offset,
 | 
| -          max_chars > rbb->capacity ? rbb->capacity : max_chars);
 | 
| -      *offset_ptr = offset + offset_correction;
 | 
| -      return rbb->util_buffer;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
 | 
| -      unsigned* remaining,
 | 
| -      unsigned* offset_ptr,
 | 
| -      unsigned max_chars) {
 | 
| -  // Cast const char* to unibrow::byte* (signedness difference).
 | 
| -  const unibrow::byte* b =
 | 
| -      reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
 | 
| -  *remaining = max_chars;
 | 
| -  *offset_ptr += max_chars;
 | 
| -  return b;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
 | 
| -      ReadBlockBuffer* rbb,
 | 
| -      unsigned* offset_ptr,
 | 
| -      unsigned max_chars) {
 | 
| -  unsigned chars_read = 0;
 | 
| -  unsigned offset = *offset_ptr;
 | 
| -  const uint16_t* data = GetChars();
 | 
| -  while (chars_read < max_chars) {
 | 
| -    uint16_t c = data[offset];
 | 
| -    if (c <= kMaxAsciiCharCode) {
 | 
| -      // Fast case for ASCII characters. Cursor is an input output argument.
 | 
| -      if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
 | 
| -                                                          rbb->util_buffer,
 | 
| -                                                          rbb->capacity,
 | 
| -                                                          rbb->cursor))
 | 
| -        break;
 | 
| -    } else {
 | 
| -      if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
 | 
| -                                                             rbb->util_buffer,
 | 
| -                                                             rbb->capacity,
 | 
| -                                                             rbb->cursor))
 | 
| -        break;
 | 
| -    }
 | 
| -    offset++;
 | 
| -    chars_read++;
 | 
| -  }
 | 
| -  *offset_ptr = offset;
 | 
| -  rbb->remaining += chars_read;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void SeqOneByteString::SeqOneByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
 | 
| -                                                 unsigned* offset_ptr,
 | 
| -                                                 unsigned max_chars) {
 | 
| -  unsigned capacity = rbb->capacity - rbb->cursor;
 | 
| -  if (max_chars > capacity) max_chars = capacity;
 | 
| -  memcpy(rbb->util_buffer + rbb->cursor,
 | 
| -         reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
 | 
| -             *offset_ptr * kCharSize,
 | 
| -         max_chars);
 | 
| -  rbb->remaining += max_chars;
 | 
| -  *offset_ptr += max_chars;
 | 
| -  rbb->cursor += max_chars;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
 | 
| -      ReadBlockBuffer* rbb,
 | 
| -      unsigned* offset_ptr,
 | 
| -      unsigned max_chars) {
 | 
| -  unsigned capacity = rbb->capacity - rbb->cursor;
 | 
| -  if (max_chars > capacity) max_chars = capacity;
 | 
| -  memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
 | 
| -  rbb->remaining += max_chars;
 | 
| -  *offset_ptr += max_chars;
 | 
| -  rbb->cursor += max_chars;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -// This method determines the type of string involved and then copies
 | 
| -// a whole chunk of characters into a buffer, or returns a pointer to a buffer
 | 
| -// where they can be found.  The pointer is not necessarily valid across a GC
 | 
| -// (see AsciiStringReadBlock).
 | 
| -const unibrow::byte* String::ReadBlock(String* input,
 | 
| -                                       ReadBlockBuffer* rbb,
 | 
| -                                       unsigned* offset_ptr,
 | 
| -                                       unsigned max_chars) {
 | 
| -  ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
 | 
| -  if (max_chars == 0) {
 | 
| -    rbb->remaining = 0;
 | 
| -    return NULL;
 | 
| -  }
 | 
| -  switch (StringShape(input).representation_tag()) {
 | 
| -    case kSeqStringTag:
 | 
| -      if (input->IsOneByteRepresentation()) {
 | 
| -        SeqOneByteString* str = SeqOneByteString::cast(input);
 | 
| -        return str->SeqOneByteStringReadBlock(&rbb->remaining,
 | 
| -                                            offset_ptr,
 | 
| -                                            max_chars);
 | 
| -      } else {
 | 
| -        SeqTwoByteString* str = SeqTwoByteString::cast(input);
 | 
| -        str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
 | 
| -                                                 offset_ptr,
 | 
| -                                                 max_chars);
 | 
| -        return rbb->util_buffer;
 | 
| -      }
 | 
| -    case kConsStringTag:
 | 
| -      return ConsString::cast(input)->ConsStringReadBlock(rbb,
 | 
| -                                                          offset_ptr,
 | 
| -                                                          max_chars);
 | 
| -    case kExternalStringTag:
 | 
| -      if (input->IsOneByteRepresentation()) {
 | 
| -        return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
 | 
| -            &rbb->remaining,
 | 
| -            offset_ptr,
 | 
| -            max_chars);
 | 
| -      } else {
 | 
| -        ExternalTwoByteString::cast(input)->
 | 
| -            ExternalTwoByteStringReadBlockIntoBuffer(rbb,
 | 
| -                                                     offset_ptr,
 | 
| -                                                     max_chars);
 | 
| -        return rbb->util_buffer;
 | 
| -      }
 | 
| -    case kSlicedStringTag:
 | 
| -      return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
 | 
| -                                                              offset_ptr,
 | 
| -                                                              max_chars);
 | 
| -    default:
 | 
| -      break;
 | 
| -  }
 | 
| -
 | 
| -  UNREACHABLE();
 | 
| -  return 0;
 | 
| -}
 | 
| -
 | 
| -
 | 
|  void Relocatable::PostGarbageCollectionProcessing() {
 | 
|    Isolate* isolate = Isolate::Current();
 | 
|    Relocatable* current = isolate->relocatable_top();
 | 
| @@ -7023,11 +6777,6 @@ void FlatStringReader::PostGarbageCollection() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void StringInputBuffer::Seek(unsigned pos) {
 | 
| -  Reset(pos, input_);
 | 
| -}
 | 
| -
 | 
| -
 | 
|  String* ConsStringIteratorOp::Operate(String* string,
 | 
|                                        unsigned* offset_out,
 | 
|                                        int32_t* type_out,
 | 
| @@ -7163,154 +6912,6 @@ String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
 | 
|  }
 | 
|  
 | 
|  
 | 
| -// 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
 | 
| -// to fill up a buffer.
 | 
| -void String::ReadBlockIntoBuffer(String* input,
 | 
| -                                 ReadBlockBuffer* rbb,
 | 
| -                                 unsigned* offset_ptr,
 | 
| -                                 unsigned max_chars) {
 | 
| -  ASSERT(*offset_ptr <= (unsigned)input->length());
 | 
| -  if (max_chars == 0) return;
 | 
| -
 | 
| -  switch (StringShape(input).representation_tag()) {
 | 
| -    case kSeqStringTag:
 | 
| -      if (input->IsOneByteRepresentation()) {
 | 
| -        SeqOneByteString::cast(input)->SeqOneByteStringReadBlockIntoBuffer(rbb,
 | 
| -                                                                 offset_ptr,
 | 
| -                                                                 max_chars);
 | 
| -        return;
 | 
| -      } else {
 | 
| -        SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
 | 
| -                                                                     offset_ptr,
 | 
| -                                                                     max_chars);
 | 
| -        return;
 | 
| -      }
 | 
| -    case kConsStringTag:
 | 
| -      ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
 | 
| -                                                             offset_ptr,
 | 
| -                                                             max_chars);
 | 
| -      return;
 | 
| -    case kExternalStringTag:
 | 
| -      if (input->IsOneByteRepresentation()) {
 | 
| -        ExternalAsciiString::cast(input)->
 | 
| -            ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
 | 
| -      } else {
 | 
| -        ExternalTwoByteString::cast(input)->
 | 
| -            ExternalTwoByteStringReadBlockIntoBuffer(rbb,
 | 
| -                                                     offset_ptr,
 | 
| -                                                     max_chars);
 | 
| -       }
 | 
| -       return;
 | 
| -    case kSlicedStringTag:
 | 
| -      SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
 | 
| -                                                                 offset_ptr,
 | 
| -                                                                 max_chars);
 | 
| -      return;
 | 
| -    default:
 | 
| -      break;
 | 
| -  }
 | 
| -
 | 
| -  UNREACHABLE();
 | 
| -  return;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -const unibrow::byte* String::ReadBlock(String* input,
 | 
| -                                       unibrow::byte* util_buffer,
 | 
| -                                       unsigned capacity,
 | 
| -                                       unsigned* remaining,
 | 
| -                                       unsigned* offset_ptr) {
 | 
| -  ASSERT(*offset_ptr <= (unsigned)input->length());
 | 
| -  unsigned chars = input->length() - *offset_ptr;
 | 
| -  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
 | 
| -  const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
 | 
| -  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
 | 
| -  *remaining = rbb.remaining;
 | 
| -  return answer;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -const unibrow::byte* String::ReadBlock(String** raw_input,
 | 
| -                                       unibrow::byte* util_buffer,
 | 
| -                                       unsigned capacity,
 | 
| -                                       unsigned* remaining,
 | 
| -                                       unsigned* offset_ptr) {
 | 
| -  Handle<String> input(raw_input);
 | 
| -  ASSERT(*offset_ptr <= (unsigned)input->length());
 | 
| -  unsigned chars = input->length() - *offset_ptr;
 | 
| -  if (chars > capacity) chars = capacity;
 | 
| -  ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
 | 
| -  ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
 | 
| -  ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
 | 
| -  *remaining = rbb.remaining;
 | 
| -  return rbb.util_buffer;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -// This will iterate unless the block of string data spans two 'halves' of
 | 
| -// a ConsString, in which case it will recurse.  Since the block of string
 | 
| -// data to be read has a maximum size this limits the maximum recursion
 | 
| -// depth to something sane.  Since C++ does not have tail call recursion
 | 
| -// elimination, the iteration must be explicit.
 | 
| -void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
 | 
| -                                               unsigned* offset_ptr,
 | 
| -                                               unsigned max_chars) {
 | 
| -  ConsString* current = this;
 | 
| -  unsigned offset = *offset_ptr;
 | 
| -  int offset_correction = 0;
 | 
| -
 | 
| -  while (true) {
 | 
| -    String* left = current->first();
 | 
| -    unsigned left_length = (unsigned)left->length();
 | 
| -    if (left_length > offset &&
 | 
| -      max_chars <= left_length - offset) {
 | 
| -      // Left hand side only - iterate unless we have reached the bottom of
 | 
| -      // the cons tree.
 | 
| -      if (StringShape(left).IsCons()) {
 | 
| -        current = ConsString::cast(left);
 | 
| -        continue;
 | 
| -      } else {
 | 
| -        String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
 | 
| -        *offset_ptr = offset + offset_correction;
 | 
| -        return;
 | 
| -      }
 | 
| -    } else if (left_length <= offset) {
 | 
| -      // Right hand side only - iterate unless we have reached the bottom of
 | 
| -      // the cons tree.
 | 
| -      offset -= left_length;
 | 
| -      offset_correction += left_length;
 | 
| -      String* right = current->second();
 | 
| -      if (StringShape(right).IsCons()) {
 | 
| -        current = ConsString::cast(right);
 | 
| -        continue;
 | 
| -      } else {
 | 
| -        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
 | 
| -        *offset_ptr = offset + offset_correction;
 | 
| -        return;
 | 
| -      }
 | 
| -    } else {
 | 
| -      // The block to be read spans two sides of the ConsString, so we recurse.
 | 
| -      // First recurse on the left.
 | 
| -      max_chars -= left_length - offset;
 | 
| -      String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
 | 
| -      // We may have reached the max or there may not have been enough space
 | 
| -      // in the buffer for the characters in the left hand side.
 | 
| -      if (offset == left_length) {
 | 
| -        // Recurse on the right.
 | 
| -        String* right = String::cast(current->second());
 | 
| -        offset -= left_length;
 | 
| -        offset_correction += left_length;
 | 
| -        String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
 | 
| -      }
 | 
| -      *offset_ptr = offset + offset_correction;
 | 
| -      return;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -
 | 
|  uint16_t ConsString::ConsStringGet(int index) {
 | 
|    ASSERT(index >= 0 && index < this->length());
 | 
|  
 | 
| @@ -7347,26 +6948,6 @@ uint16_t SlicedString::SlicedStringGet(int index) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -const unibrow::byte* SlicedString::SlicedStringReadBlock(
 | 
| -    ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
 | 
| -  unsigned offset = this->offset();
 | 
| -  *offset_ptr += offset;
 | 
| -  const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
 | 
| -                                                  buffer, offset_ptr, chars);
 | 
| -  *offset_ptr -= offset;
 | 
| -  return answer;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void SlicedString::SlicedStringReadBlockIntoBuffer(
 | 
| -    ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
 | 
| -  unsigned offset = this->offset();
 | 
| -  *offset_ptr += offset;
 | 
| -  String::ReadBlockIntoBuffer(String::cast(parent()),
 | 
| -                              buffer, offset_ptr, chars);
 | 
| -  *offset_ptr -= offset;
 | 
| -}
 | 
| -
 | 
|  template <typename sinkchar>
 | 
|  void String::WriteToFlat(String* src,
 | 
|                           sinkchar* sink,
 | 
| 
 |