| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 7667e89a3cbdd35971282d42c920a52aa61f2597..11e2eb559e79d01328b1494d68a19da5df29626a 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -872,11 +872,14 @@ class ParserLog BASE_EMBEDDED {
|
| // Records the occurrence of a function.
|
| virtual FunctionEntry LogFunction(int start) { return FunctionEntry(); }
|
| virtual void LogSymbol(int start, Vector<const char> symbol) {}
|
| + virtual void LogError() { }
|
| // Return the current position in the function entry log.
|
| virtual int function_position() { return 0; }
|
| virtual int symbol_position() { return 0; }
|
| virtual int symbol_ids() { return 0; }
|
| - virtual void LogError() { }
|
| + virtual Vector<unsigned> ExtractData() {
|
| + return Vector<unsigned>();
|
| + };
|
| };
|
|
|
|
|
| @@ -889,9 +892,14 @@ class AstBuildingParserFactory : public ParserFactory {
|
|
|
| virtual Handle<String> LookupSymbol(int symbol_id,
|
| Vector<const char> string) {
|
| - // If there is no preparse data, we have no simpler way to identify similar
|
| - // symbols.
|
| - if (symbol_id < 0) return Factory::LookupSymbol(string);
|
| + // Length of symbol cache is the number of identified symbols.
|
| + // If we are larger than that, or negative, it's not a cached symbol.
|
| + // This might also happen if there is no preparser symbol data, even
|
| + // if there is some preparser data.
|
| + if (static_cast<unsigned>(symbol_id)
|
| + >= static_cast<unsigned>(symbol_cache_.length())) {
|
| + return Factory::LookupSymbol(string);
|
| + }
|
| return LookupCachedSymbol(symbol_id, string);
|
| }
|
|
|
| @@ -933,10 +941,55 @@ class AstBuildingParserFactory : public ParserFactory {
|
| };
|
|
|
|
|
| -class ParserRecorder: public ParserLog {
|
| +// Record only functions.
|
| +class PartialParserRecorder: public ParserLog {
|
| public:
|
| - ParserRecorder();
|
| + PartialParserRecorder();
|
| virtual FunctionEntry LogFunction(int start);
|
| +
|
| + virtual int function_position() { return function_store_.size(); }
|
| +
|
| + virtual void LogError() { }
|
| +
|
| + virtual void LogMessage(Scanner::Location loc,
|
| + const char* message,
|
| + Vector<const char*> args);
|
| +
|
| + virtual Vector<unsigned> ExtractData() {
|
| + int function_size = function_store_.size();
|
| + int total_size = ScriptDataImpl::kHeaderSize + function_size;
|
| + Vector<unsigned> data = Vector<unsigned>::New(total_size);
|
| + preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
|
| + preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
|
| + memcpy(data.start(), preamble_, sizeof(preamble_));
|
| + int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
|
| + if (function_size > 0) {
|
| + function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
|
| + symbol_start));
|
| + }
|
| + return data;
|
| + }
|
| +
|
| + protected:
|
| + bool has_error() {
|
| + return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
|
| + }
|
| +
|
| + void WriteString(Vector<const char> str);
|
| +
|
| + Collector<unsigned> function_store_;
|
| + unsigned preamble_[ScriptDataImpl::kHeaderSize];
|
| +#ifdef DEBUG
|
| + int prev_start;
|
| +#endif
|
| +};
|
| +
|
| +
|
| +// Record both functions and symbols.
|
| +class CompleteParserRecorder: public PartialParserRecorder {
|
| + public:
|
| + CompleteParserRecorder();
|
| +
|
| virtual void LogSymbol(int start, Vector<const char> literal) {
|
| int hash = vector_hash(literal);
|
| HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
|
| @@ -953,11 +1006,8 @@ class ParserRecorder: public ParserLog {
|
| symbol_store_.Add(id - 1);
|
| }
|
| }
|
| - virtual void LogError() { }
|
| - virtual void LogMessage(Scanner::Location loc,
|
| - const char* message,
|
| - Vector<const char*> args);
|
| - Vector<unsigned> ExtractData() {
|
| +
|
| + virtual Vector<unsigned> ExtractData() {
|
| int function_size = function_store_.size();
|
| int symbol_size = symbol_store_.size();
|
| int total_size = ScriptDataImpl::kHeaderSize + function_size + symbol_size;
|
| @@ -976,11 +1026,9 @@ class ParserRecorder: public ParserLog {
|
| return data;
|
| }
|
|
|
| - virtual int function_position() { return function_store_.size(); }
|
| virtual int symbol_position() { return symbol_store_.size(); }
|
| virtual int symbol_ids() { return symbol_id_; }
|
| private:
|
| - Collector<unsigned> function_store_;
|
| Collector<unsigned> symbol_store_;
|
| Collector<Vector<const char> > symbol_entries_;
|
| HashMap symbol_table_;
|
| @@ -1004,16 +1052,6 @@ class ParserRecorder: public ParserLog {
|
| if (string2->length() != length) return false;
|
| return memcmp(string1->start(), string2->start(), length) == 0;
|
| }
|
| -
|
| - unsigned preamble_[ScriptDataImpl::kHeaderSize];
|
| -#ifdef DEBUG
|
| - int prev_start;
|
| -#endif
|
| -
|
| - bool has_error() {
|
| - return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
|
| - }
|
| - void WriteString(Vector<const char> str);
|
| };
|
|
|
|
|
| @@ -1088,15 +1126,8 @@ bool ScriptDataImpl::SanityCheck() {
|
| }
|
|
|
|
|
| -ParserRecorder::ParserRecorder()
|
| - : function_store_(0),
|
| - symbol_store_(0),
|
| - symbol_entries_(0),
|
| - symbol_table_(vector_compare),
|
| - symbol_id_(0) {
|
| -#ifdef DEBUG
|
| - prev_start = -1;
|
| -#endif
|
| +
|
| +PartialParserRecorder::PartialParserRecorder() : function_store_(0) {
|
| preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
|
| preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
|
| preamble_[ScriptDataImpl::kHasErrorOffset] = false;
|
| @@ -1104,10 +1135,22 @@ ParserRecorder::ParserRecorder()
|
| preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
|
| preamble_[ScriptDataImpl::kSizeOffset] = 0;
|
| ASSERT_EQ(6, ScriptDataImpl::kHeaderSize);
|
| +#ifdef DEBUG
|
| + prev_start = -1;
|
| +#endif
|
| }
|
|
|
|
|
| -void ParserRecorder::WriteString(Vector<const char> str) {
|
| +CompleteParserRecorder::CompleteParserRecorder()
|
| + : PartialParserRecorder(),
|
| + symbol_store_(0),
|
| + symbol_entries_(0),
|
| + symbol_table_(vector_compare),
|
| + symbol_id_(0) {
|
| +}
|
| +
|
| +
|
| +void PartialParserRecorder::WriteString(Vector<const char> str) {
|
| function_store_.Add(str.length());
|
| for (int i = 0; i < str.length(); i++) {
|
| function_store_.Add(str[i]);
|
| @@ -1127,8 +1170,9 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
| }
|
|
|
|
|
| -void ParserRecorder::LogMessage(Scanner::Location loc, const char* message,
|
| - Vector<const char*> args) {
|
| +void PartialParserRecorder::LogMessage(Scanner::Location loc,
|
| + const char* message,
|
| + Vector<const char*> args) {
|
| if (has_error()) return;
|
| preamble_[ScriptDataImpl::kHasErrorOffset] = true;
|
| function_store_.Reset();
|
| @@ -1183,7 +1227,7 @@ unsigned* ScriptDataImpl::ReadAddress(int position) {
|
| }
|
|
|
|
|
| -FunctionEntry ParserRecorder::LogFunction(int start) {
|
| +FunctionEntry PartialParserRecorder::LogFunction(int start) {
|
| #ifdef DEBUG
|
| ASSERT(start > prev_start);
|
| prev_start = start;
|
| @@ -1206,7 +1250,7 @@ class AstBuildingParser : public Parser {
|
| factory(),
|
| log(),
|
| pre_data),
|
| - factory_(pre_data ? pre_data->symbol_count() : 16) { }
|
| + factory_(pre_data ? pre_data->symbol_count() : 0) { }
|
| virtual void ReportMessageAt(Scanner::Location loc, const char* message,
|
| Vector<const char*> args);
|
| virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
|
| @@ -1223,23 +1267,44 @@ class AstBuildingParser : public Parser {
|
| class PreParser : public Parser {
|
| public:
|
| PreParser(Handle<Script> script, bool allow_natives_syntax,
|
| - v8::Extension* extension)
|
| + v8::Extension* extension, ParserLog* recorder)
|
| : Parser(script, allow_natives_syntax, extension, PREPARSE,
|
| - factory(), recorder(), NULL),
|
| + factory(), recorder, NULL),
|
| factory_(true) { }
|
| virtual void ReportMessageAt(Scanner::Location loc, const char* message,
|
| Vector<const char*> args);
|
| virtual VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
|
| FunctionLiteral* fun, bool resolve, bool* ok);
|
| ParserFactory* factory() { return &factory_; }
|
| - ParserRecorder* recorder() { return &recorder_; }
|
| + virtual PartialParserRecorder* recorder() = 0;
|
|
|
| private:
|
| - ParserRecorder recorder_;
|
| ParserFactory factory_;
|
| };
|
|
|
|
|
| +class CompletePreParser : public PreParser {
|
| + public:
|
| + CompletePreParser(Handle<Script> script, bool allow_natives_syntax,
|
| + v8::Extension* extension)
|
| + : PreParser(script, allow_natives_syntax, extension, &recorder_) { }
|
| + virtual PartialParserRecorder* recorder() { return &recorder_; }
|
| + private:
|
| + CompleteParserRecorder recorder_;
|
| +};
|
| +
|
| +
|
| +class PartialPreParser : public PreParser {
|
| + public:
|
| + PartialPreParser(Handle<Script> script, bool allow_natives_syntax,
|
| + v8::Extension* extension)
|
| + : PreParser(script, allow_natives_syntax, extension, &recorder_) { }
|
| + virtual PartialParserRecorder* recorder() { return &recorder_; }
|
| + private:
|
| + PartialParserRecorder recorder_;
|
| +};
|
| +
|
| +
|
| Scope* AstBuildingParserFactory::NewScope(Scope* parent, Scope::Type type,
|
| bool inside_with) {
|
| Scope* result = new Scope(parent, type);
|
| @@ -5413,6 +5478,25 @@ bool ScriptDataImpl::HasError() {
|
| }
|
|
|
|
|
| +// Preparse, but only collect data that is immediately useful,
|
| +// even if the preparser data is only used once.
|
| +ScriptDataImpl* PartialPreParse(Handle<String> source,
|
| + unibrow::CharacterStream* stream,
|
| + v8::Extension* extension) {
|
| + Handle<Script> no_script;
|
| + bool allow_natives_syntax =
|
| + always_allow_natives_syntax ||
|
| + FLAG_allow_natives_syntax ||
|
| + Bootstrapper::IsActive();
|
| + PartialPreParser parser(no_script, allow_natives_syntax, extension);
|
| + if (!parser.PreParseProgram(source, stream)) return NULL;
|
| + // Extract the accumulated data from the recorder as a single
|
| + // contiguous vector that we are responsible for disposing.
|
| + Vector<unsigned> store = parser.recorder()->ExtractData();
|
| + return new ScriptDataImpl(store);
|
| +}
|
| +
|
| +
|
| ScriptDataImpl* PreParse(Handle<String> source,
|
| unibrow::CharacterStream* stream,
|
| v8::Extension* extension) {
|
| @@ -5421,7 +5505,7 @@ ScriptDataImpl* PreParse(Handle<String> source,
|
| always_allow_natives_syntax ||
|
| FLAG_allow_natives_syntax ||
|
| Bootstrapper::IsActive();
|
| - PreParser parser(no_script, allow_natives_syntax, extension);
|
| + CompletePreParser parser(no_script, allow_natives_syntax, extension);
|
| if (!parser.PreParseProgram(source, stream)) return NULL;
|
| // Extract the accumulated data from the recorder as a single
|
| // contiguous vector that we are responsible for disposing.
|
|
|