Index: src/preparser-api.cc |
diff --git a/src/preparser-api.cc b/src/preparser-api.cc |
index f096e941b704ab29f3516176ea1aa000ed766bd7..df2cf2b4ebe8be31d369dd4a21ee7eccc0045d73 100644 |
--- a/src/preparser-api.cc |
+++ b/src/preparser-api.cc |
@@ -39,39 +39,82 @@ namespace v8 { |
namespace internal { |
// UTF16Buffer based on a v8::UnicodeInputStream. |
-class InputStreamUTF16Buffer : public UTF16Buffer { |
+class InputStreamUTF16Buffer : public UC16CharacterStream { |
public: |
- explicit InputStreamUTF16Buffer(UnicodeInputStream* stream) |
- : UTF16Buffer(), |
- stream_(stream) { } |
+ explicit InputStreamUTF16Buffer(v8::UnicodeInputStream* stream) |
+ : UC16CharacterStream(), |
+ stream_(stream), |
+ pushback_active_(false) { |
+ buffer_cursor_ = buffer_end_ = buffer_ + kPushBackSize; |
+ } |
virtual ~InputStreamUTF16Buffer() { } |
- virtual void PushBack(uc32 ch) { |
+ virtual void PushBack(uc16 ch) { |
+ ASSERT(pos_ > 0); |
+ if (buffer_cursor_ > buffer_) { |
+ // While we can stay within the buffer, just do so. |
+ *--buffer_cursor_ = ch; |
+ pos_--; |
+ return; |
+ } |
+ if (!pushback_active_) { |
+ // Push back the entire buffer to the stream and let the |
+ // stream handle pushbacks from now. |
+ // We leave buffer_cursor_ == buffer_end_, so the next read |
+ // will fill the buffer from the current position. |
+ // This should happen exceedingly rarely. |
+ while (buffer_end_ > buffer_) { |
+ stream_->PushBack(*--buffer_end_); |
+ } |
+ buffer_cursor_ = buffer_end_; |
+ pushback_active_ = true; |
+ } |
stream_->PushBack(ch); |
pos_--; |
} |
- virtual uc32 Advance() { |
- uc32 result = stream_->Next(); |
- if (result >= 0) pos_++; |
- return result; |
+ protected: |
+ virtual bool ReadBlock() { |
+ // Copy the top of the buffer into the pushback area. |
+ pushback_active_ = false; |
+ int32_t value; |
+ uc16* buffer_start = buffer_ + kPushBackSize; |
+ buffer_cursor_ = buffer_end_ = buffer_start; |
+ while ((value = stream_->Next()) >= 0) { |
+ if (value > static_cast<int32_t>(unibrow::Utf8::kMaxThreeByteChar)) { |
+ value = unibrow::Utf8::kBadChar; |
+ } |
+ // buffer_end_ is a const pointer, but buffer_ is writable. |
+ buffer_start[buffer_end_++ - buffer_start] = static_cast<uc16>(value); |
+ if (buffer_end_ == buffer_ + kPushBackSize + kBufferSize) break; |
+ } |
+ return buffer_end_ > buffer_start; |
} |
- virtual void SeekForward(int pos) { |
+ virtual unsigned SlowSeekForward(unsigned pos) { |
// Seeking in the input is not used by preparsing. |
// It's only used by the real parser based on preparser data. |
UNIMPLEMENTED(); |
+ return 0; |
} |
private: |
+ static const unsigned kBufferSize = 512; |
+ static const unsigned kPushBackSize = 16; |
v8::UnicodeInputStream* const stream_; |
+ // Buffer holding first kPushBackSize characters of pushback buffer, |
+ // then kBufferSize chars of read-ahead. |
+ // The pushback buffer is only used if pushing back characters past |
+ // the start of a block. |
+ uc16 buffer_[kBufferSize + kPushBackSize]; |
+ bool pushback_active_; |
}; |
class StandAloneJavaScriptScanner : public JavaScriptScanner { |
public: |
- void Initialize(UTF16Buffer* source) { |
+ void Initialize(UC16CharacterStream* source) { |
source_ = source; |
literal_flags_ = kLiteralString | kLiteralIdentifier; |
Init(); |