| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 2bf73c4bfb4213b679ff584380e95f5367672980..f0b6f357e0128b247745014473b472b9571596d3 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -867,11 +867,10 @@ class ParserLog BASE_EMBEDDED {
|
| public:
|
| virtual ~ParserLog() { }
|
|
|
| - // Records the occurrence of a function. The returned object is
|
| - // only guaranteed to be valid until the next function has been
|
| - // logged.
|
| + // Records the occurrence of a function.
|
| virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); }
|
| -
|
| + // Return the current position in the function entry log.
|
| + virtual int position() { return 0; }
|
| virtual void LogError() { }
|
| };
|
|
|
| @@ -913,30 +912,45 @@ class ParserRecorder: public ParserLog {
|
| const char* message,
|
| Vector<const char*> args);
|
| Vector<unsigned> ExtractData() {
|
| - return store_.ToVector();
|
| + int total_size = ScriptDataImpl::kHeaderSize + store_.size();
|
| + Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
| + memcpy(data.start(), preamble_, sizeof(preamble_));
|
| + if (ScriptDataImpl::kHeaderSize < total_size) {
|
| + store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize, total_size));
|
| + }
|
| + return data;
|
| }
|
| + virtual int position() { return store_.size(); }
|
| private:
|
| - bool has_error_;
|
| Collector<unsigned> store_;
|
| - Vector<unsigned> preamble_;
|
| + unsigned preamble_[ScriptDataImpl::kHeaderSize];
|
| +#ifdef DEBUG
|
| + int prev_start;
|
| +#endif
|
|
|
| - Collector<unsigned>* store() { return &store_; }
|
| + bool has_error() {
|
| + return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
|
| + }
|
| void WriteString(Vector<const char> str);
|
| };
|
|
|
|
|
| -FunctionEntry ScriptDataImpl::GetFunctionEnd(int start) {
|
| - if (nth(last_entry_).start_pos() > start) {
|
| - // If the last entry we looked up is higher than what we're
|
| - // looking for then it's useless and we reset it.
|
| - last_entry_ = 0;
|
| - }
|
| - for (int i = last_entry_; i < EntryCount(); i++) {
|
| - FunctionEntry entry = nth(i);
|
| - if (entry.start_pos() == start) {
|
| - last_entry_ = i;
|
| - return entry;
|
| - }
|
| +void ScriptDataImpl::SkipFunctionEntry(int start) {
|
| + ASSERT(index_ + FunctionEntry::kSize <= store_.length());
|
| + ASSERT(static_cast<int>(store_[index_]) == start);
|
| + index_ += FunctionEntry::kSize;
|
| +}
|
| +
|
| +
|
| +FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
|
| + // The current pre-data entry must be a FunctionEntry with the given
|
| + // start position.
|
| + if ((index_ + FunctionEntry::kSize <= store_.length())
|
| + && (static_cast<int>(store_[index_]) == start)) {
|
| + int index = index_;
|
| + index_ += FunctionEntry::kSize;
|
| + return FunctionEntry(store_.SubVector(index,
|
| + index + FunctionEntry::kSize));
|
| }
|
| return FunctionEntry();
|
| }
|
| @@ -952,31 +966,23 @@ bool ScriptDataImpl::SanityCheck() {
|
| }
|
|
|
|
|
| -int ScriptDataImpl::EntryCount() {
|
| - return (store_.length() - kHeaderSize) / FunctionEntry::kSize;
|
| -}
|
| -
|
| -
|
| -FunctionEntry ScriptDataImpl::nth(int n) {
|
| - int offset = kHeaderSize + n * FunctionEntry::kSize;
|
| - return FunctionEntry(Vector<unsigned>(store_.start() + offset,
|
| - FunctionEntry::kSize));
|
| -}
|
| -
|
| -
|
| ParserRecorder::ParserRecorder()
|
| - : has_error_(false), store_(ScriptDataImpl::kHeaderSize) {
|
| - preamble_ = store()->AddBlock(ScriptDataImpl::kHeaderSize, 0);
|
| + : store_(0) {
|
| +#ifdef DEBUG
|
| + prev_start = -1;
|
| +#endif
|
| preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
|
| preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
|
| preamble_[ScriptDataImpl::kHasErrorOffset] = false;
|
| + preamble_[ScriptDataImpl::kSizeOffset] = 0;
|
| + ASSERT_EQ(4, ScriptDataImpl::kHeaderSize);
|
| }
|
|
|
|
|
| void ParserRecorder::WriteString(Vector<const char> str) {
|
| - store()->Add(str.length());
|
| + store_.Add(str.length());
|
| for (int i = 0; i < str.length(); i++) {
|
| - store()->Add(str[i]);
|
| + store_.Add(str[i]);
|
| }
|
| }
|
|
|
| @@ -995,15 +1001,12 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
|
|
| void ParserRecorder::LogMessage(Scanner::Location loc, const char* message,
|
| Vector<const char*> args) {
|
| - if (has_error_) return;
|
| - store()->Reset();
|
| - preamble_ = store()->AddBlock(ScriptDataImpl::kHeaderSize, 0);
|
| - preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
|
| - preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
|
| + if (has_error()) return;
|
| preamble_[ScriptDataImpl::kHasErrorOffset] = true;
|
| - store()->Add(loc.beg_pos);
|
| - store()->Add(loc.end_pos);
|
| - store()->Add(args.length());
|
| + store_.Reset();
|
| + store_.Add(loc.beg_pos);
|
| + store_.Add(loc.end_pos);
|
| + store_.Add(args.length());
|
| WriteString(CStrVector(message));
|
| for (int i = 0; i < args.length(); i++) {
|
| WriteString(CStrVector(args[i]));
|
| @@ -1046,10 +1049,22 @@ unsigned* ScriptDataImpl::ReadAddress(int position) {
|
| return &store_[ScriptDataImpl::kHeaderSize + position];
|
| }
|
|
|
| +void ScriptDataImpl::FindStart(int position) {
|
| + // Only search forwards, and linearly for now.
|
| + while ((index_ < store_.length())
|
| + && (static_cast<int>(store_[index_])) < position) {
|
| + index_ += FunctionEntry::kSize;
|
| + }
|
| +}
|
| +
|
|
|
| FunctionEntry ParserRecorder::LogFunction(int start) {
|
| - if (has_error_) return FunctionEntry();
|
| - FunctionEntry result(store()->AddBlock(FunctionEntry::kSize, 0));
|
| +#ifdef DEBUG
|
| + ASSERT(start > prev_start);
|
| + prev_start = start;
|
| +#endif
|
| + if (has_error()) return FunctionEntry();
|
| + FunctionEntry result(store_.AddBlock(FunctionEntry::kSize, 0));
|
| result.set_start_pos(start);
|
| return result;
|
| }
|
| @@ -3939,43 +3954,52 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
| bool is_lazily_compiled =
|
| mode() == PARSE_LAZILY && top_scope_->HasTrivialOuterContext();
|
|
|
| + int function_block_pos = scanner_.location().beg_pos;
|
| int materialized_literal_count;
|
| int expected_property_count;
|
| + int end_pos;
|
| bool only_simple_this_property_assignments;
|
| Handle<FixedArray> this_property_assignments;
|
| if (is_lazily_compiled && pre_data() != NULL) {
|
| - FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
|
| + FunctionEntry entry = pre_data()->GetFunctionEntry(function_block_pos);
|
| if (!entry.is_valid()) {
|
| ReportInvalidPreparseData(name, CHECK_OK);
|
| }
|
| - int end_pos = entry.end_pos();
|
| - if (end_pos <= start_pos) {
|
| + end_pos = entry.end_pos();
|
| + if (end_pos <= function_block_pos) {
|
| // End position greater than end of stream is safe, and hard to check.
|
| ReportInvalidPreparseData(name, CHECK_OK);
|
| }
|
| - Counters::total_preparse_skipped.Increment(end_pos - start_pos);
|
| + Counters::total_preparse_skipped.Increment(end_pos - function_block_pos);
|
| scanner_.SeekForward(end_pos);
|
| + pre_data()->Skip(entry.predata_skip());
|
| materialized_literal_count = entry.literal_count();
|
| expected_property_count = entry.property_count();
|
| only_simple_this_property_assignments = false;
|
| this_property_assignments = Factory::empty_fixed_array();
|
| + Expect(Token::RBRACE, CHECK_OK);
|
| } else {
|
| + if (pre_data() != NULL) {
|
| + // Skip pre-data entry for non-lazily compiled function.
|
| + pre_data()->SkipFunctionEntry(function_block_pos);
|
| + }
|
| + FunctionEntry entry = log()->LogFunction(function_block_pos);
|
| + int predata_position_before = log()->position();
|
| ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
|
| materialized_literal_count = temp_scope.materialized_literal_count();
|
| expected_property_count = temp_scope.expected_property_count();
|
| only_simple_this_property_assignments =
|
| temp_scope.only_simple_this_property_assignments();
|
| this_property_assignments = temp_scope.this_property_assignments();
|
| - }
|
| -
|
| - Expect(Token::RBRACE, CHECK_OK);
|
| - int end_pos = scanner_.location().end_pos;
|
|
|
| - FunctionEntry entry = log()->LogFunction(start_pos);
|
| - if (entry.is_valid()) {
|
| - entry.set_end_pos(end_pos);
|
| - entry.set_literal_count(materialized_literal_count);
|
| - entry.set_property_count(expected_property_count);
|
| + Expect(Token::RBRACE, CHECK_OK);
|
| + end_pos = scanner_.location().end_pos;
|
| + if (entry.is_valid()) {
|
| + entry.set_end_pos(end_pos);
|
| + entry.set_literal_count(materialized_literal_count);
|
| + entry.set_property_count(expected_property_count);
|
| + entry.set_predata_skip(log()->position() - predata_position_before);
|
| + }
|
| }
|
|
|
| FunctionLiteral* function_literal =
|
|
|