| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 5b306a7035efc3adce275a201a4f6edd0220894f..d25569d78d39777ceb70925dd77477e301d6793d 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -182,147 +182,86 @@ void RegExpBuilder::AddQuantifierToAtom(
|
| }
|
|
|
|
|
| -ScriptData* ScriptData::New(const char* data, int length, bool owns_store) {
|
| - // The length is obviously invalid.
|
| - if (length % sizeof(unsigned) != 0) {
|
| - return NULL;
|
| - }
|
| -
|
| - int deserialized_data_length = length / sizeof(unsigned);
|
| - unsigned* deserialized_data;
|
| - owns_store =
|
| - owns_store || reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0;
|
| - if (owns_store) {
|
| - // Copy the data to align it.
|
| - deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
|
| - i::CopyBytes(reinterpret_cast<char*>(deserialized_data),
|
| - data, static_cast<size_t>(length));
|
| - } else {
|
| - // If aligned, don't create a copy of the data.
|
| - deserialized_data = reinterpret_cast<unsigned*>(const_cast<char*>(data));
|
| - }
|
| - return new ScriptData(
|
| - Vector<unsigned>(deserialized_data, deserialized_data_length),
|
| - owns_store);
|
| -}
|
| -
|
| -
|
| -FunctionEntry ScriptData::GetFunctionEntry(int start) {
|
| +FunctionEntry ParseData::GetFunctionEntry(int start) {
|
| // The current pre-data entry must be a FunctionEntry with the given
|
| // start position.
|
| - if ((function_index_ + FunctionEntry::kSize <= store_.length())
|
| - && (static_cast<int>(store_[function_index_]) == start)) {
|
| + if ((function_index_ + FunctionEntry::kSize <= Length()) &&
|
| + (static_cast<int>(Data()[function_index_]) == start)) {
|
| int index = function_index_;
|
| function_index_ += FunctionEntry::kSize;
|
| - return FunctionEntry(store_.SubVector(index,
|
| - index + FunctionEntry::kSize));
|
| + Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
|
| + return FunctionEntry(subvector);
|
| }
|
| return FunctionEntry();
|
| }
|
|
|
|
|
| -int ScriptData::GetSymbolIdentifier() {
|
| - return ReadNumber(&symbol_data_);
|
| +int ParseData::FunctionCount() {
|
| + int functions_size = FunctionsSize();
|
| + if (functions_size < 0) return 0;
|
| + if (functions_size % FunctionEntry::kSize != 0) return 0;
|
| + return functions_size / FunctionEntry::kSize;
|
| }
|
|
|
|
|
| -bool ScriptData::SanityCheck() {
|
| +bool ParseData::IsSane() {
|
| // Check that the header data is valid and doesn't specify
|
| // point to positions outside the store.
|
| - if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
|
| - if (magic() != PreparseDataConstants::kMagicNumber) return false;
|
| - if (version() != PreparseDataConstants::kCurrentVersion) return false;
|
| - if (has_error()) {
|
| - // Extra sane sanity check for error message encoding.
|
| - if (store_.length() <= PreparseDataConstants::kHeaderSize
|
| - + PreparseDataConstants::kMessageTextPos) {
|
| - return false;
|
| - }
|
| - if (Read(PreparseDataConstants::kMessageStartPos) >
|
| - Read(PreparseDataConstants::kMessageEndPos)) {
|
| - return false;
|
| - }
|
| - unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
|
| - int pos = PreparseDataConstants::kMessageTextPos;
|
| - for (unsigned int i = 0; i <= arg_count; i++) {
|
| - if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
|
| - return false;
|
| - }
|
| - int length = static_cast<int>(Read(pos));
|
| - if (length < 0) return false;
|
| - pos += 1 + length;
|
| - }
|
| - if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| + int data_length = Length();
|
| + if (data_length < PreparseDataConstants::kHeaderSize) return false;
|
| + if (Magic() != PreparseDataConstants::kMagicNumber) return false;
|
| + if (Version() != PreparseDataConstants::kCurrentVersion) return false;
|
| + if (HasError()) return false;
|
| // Check that the space allocated for function entries is sane.
|
| - int functions_size =
|
| - static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
|
| + int functions_size = FunctionsSize();
|
| if (functions_size < 0) return false;
|
| if (functions_size % FunctionEntry::kSize != 0) return false;
|
| // Check that the total size has room for header and function entries.
|
| int minimum_size =
|
| PreparseDataConstants::kHeaderSize + functions_size;
|
| - if (store_.length() < minimum_size) return false;
|
| + if (data_length < minimum_size) return false;
|
| return true;
|
| }
|
|
|
|
|
| -
|
| -const char* ScriptData::ReadString(unsigned* start, int* chars) {
|
| - int length = start[0];
|
| - char* result = NewArray<char>(length + 1);
|
| - for (int i = 0; i < length; i++) {
|
| - result[i] = start[i + 1];
|
| +void ParseData::Initialize() {
|
| + // Prepares state for use.
|
| + int data_length = Length();
|
| + if (data_length >= PreparseDataConstants::kHeaderSize) {
|
| + function_index_ = PreparseDataConstants::kHeaderSize;
|
| }
|
| - result[length] = '\0';
|
| - if (chars != NULL) *chars = length;
|
| - return result;
|
| -}
|
| -
|
| -
|
| -Scanner::Location ScriptData::MessageLocation() const {
|
| - int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
|
| - int end_pos = Read(PreparseDataConstants::kMessageEndPos);
|
| - return Scanner::Location(beg_pos, end_pos);
|
| }
|
|
|
|
|
| -bool ScriptData::IsReferenceError() const {
|
| - return Read(PreparseDataConstants::kIsReferenceErrorPos);
|
| +bool ParseData::HasError() {
|
| + return Data()[PreparseDataConstants::kHasErrorOffset];
|
| }
|
|
|
|
|
| -const char* ScriptData::BuildMessage() const {
|
| - unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
|
| - return ReadString(start, NULL);
|
| +unsigned ParseData::Magic() {
|
| + return Data()[PreparseDataConstants::kMagicOffset];
|
| }
|
|
|
|
|
| -const char* ScriptData::BuildArg() const {
|
| - int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
|
| - ASSERT(arg_count == 0 || arg_count == 1);
|
| - if (arg_count == 0) {
|
| - return NULL;
|
| - }
|
| - // Position after text found by skipping past length field and
|
| - // length field content words.
|
| - int pos = PreparseDataConstants::kMessageTextPos + 1
|
| - + Read(PreparseDataConstants::kMessageTextPos);
|
| - int count = 0;
|
| - return ReadString(ReadAddress(pos), &count);
|
| +unsigned ParseData::Version() {
|
| + return Data()[PreparseDataConstants::kVersionOffset];
|
| }
|
|
|
|
|
| -unsigned ScriptData::Read(int position) const {
|
| - return store_[PreparseDataConstants::kHeaderSize + position];
|
| +int ParseData::FunctionsSize() {
|
| + return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
|
| }
|
|
|
|
|
| -unsigned* ScriptData::ReadAddress(int position) const {
|
| - return &store_[PreparseDataConstants::kHeaderSize + position];
|
| +void Parser::SetCachedData() {
|
| + if (cached_data_mode() == NO_CACHED_DATA) {
|
| + cached_parse_data_ = NULL;
|
| + } else {
|
| + ASSERT(info_->cached_data() != NULL);
|
| + if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
| + cached_parse_data_ = new ParseData(*info_->cached_data());
|
| + }
|
| + }
|
| }
|
|
|
|
|
| @@ -757,18 +696,14 @@ FunctionLiteral* ParserTraits::ParseFunctionLiteral(
|
| Parser::Parser(CompilationInfo* info)
|
| : ParserBase<ParserTraits>(&scanner_,
|
| info->isolate()->stack_guard()->real_climit(),
|
| - info->extension(),
|
| - NULL,
|
| - info->zone(),
|
| - this),
|
| + info->extension(), NULL, info->zone(), this),
|
| isolate_(info->isolate()),
|
| script_(info->script()),
|
| scanner_(isolate_->unicode_cache()),
|
| reusable_preparser_(NULL),
|
| original_scope_(NULL),
|
| target_stack_(NULL),
|
| - cached_data_(NULL),
|
| - cached_data_mode_(NO_CACHED_DATA),
|
| + cached_parse_data_(NULL),
|
| ast_value_factory_(NULL),
|
| info_(info),
|
| has_pending_error_(false),
|
| @@ -805,10 +740,10 @@ FunctionLiteral* Parser::ParseProgram() {
|
|
|
| // Initialize parser state.
|
| CompleteParserRecorder recorder;
|
| - if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| + if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
| log_ = &recorder;
|
| - } else if (cached_data_mode_ == CONSUME_CACHED_DATA) {
|
| - (*cached_data_)->Initialize();
|
| + } else if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
| + cached_parse_data_->Initialize();
|
| }
|
|
|
| source = String::Flatten(source);
|
| @@ -840,11 +775,8 @@ FunctionLiteral* Parser::ParseProgram() {
|
| }
|
| PrintF(" - took %0.3f ms]\n", ms);
|
| }
|
| - if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| - if (result != NULL) {
|
| - Vector<unsigned> store = recorder.ExtractData();
|
| - *cached_data_ = new ScriptData(store);
|
| - }
|
| + if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
| + if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
|
| log_ = NULL;
|
| }
|
| return result;
|
| @@ -3293,12 +3225,6 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
|
| }
|
|
|
|
|
| -void Parser::ReportInvalidCachedData(const AstRawString* name, bool* ok) {
|
| - ParserTraits::ReportMessage("invalid_cached_data_function", name);
|
| - *ok = false;
|
| -}
|
| -
|
| -
|
| bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
|
| if (expression->IsLiteral()) return true;
|
| MaterializedLiteral* lit = expression->AsMaterializedLiteral();
|
| @@ -3615,37 +3541,27 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
| int* expected_property_count,
|
| bool* ok) {
|
| int function_block_pos = position();
|
| - if (cached_data_mode_ == CONSUME_CACHED_DATA) {
|
| + if (cached_data_mode() == CONSUME_CACHED_DATA) {
|
| // If we have cached data, we use it to skip parsing the function body. The
|
| // data contains the information we need to construct the lazy function.
|
| FunctionEntry entry =
|
| - (*cached_data())->GetFunctionEntry(function_block_pos);
|
| - if (entry.is_valid()) {
|
| - if (entry.end_pos() <= function_block_pos) {
|
| - // End position greater than end of stream is safe, and hard to check.
|
| - ReportInvalidCachedData(function_name, ok);
|
| - if (!*ok) {
|
| - return;
|
| - }
|
| - }
|
| - scanner()->SeekForward(entry.end_pos() - 1);
|
| -
|
| - scope_->set_end_position(entry.end_pos());
|
| - Expect(Token::RBRACE, ok);
|
| - if (!*ok) {
|
| - return;
|
| - }
|
| - isolate()->counters()->total_preparse_skipped()->Increment(
|
| - scope_->end_position() - function_block_pos);
|
| - *materialized_literal_count = entry.literal_count();
|
| - *expected_property_count = entry.property_count();
|
| - scope_->SetStrictMode(entry.strict_mode());
|
| - } else {
|
| - // This case happens when we have preparse data but it doesn't contain an
|
| - // entry for the function. Fail the compilation.
|
| - ReportInvalidCachedData(function_name, ok);
|
| + cached_parse_data_->GetFunctionEntry(function_block_pos);
|
| + // Check that cached data is valid.
|
| + CHECK(entry.is_valid());
|
| + // End position greater than end of stream is safe, and hard to check.
|
| + CHECK(entry.end_pos() > function_block_pos);
|
| + scanner()->SeekForward(entry.end_pos() - 1);
|
| +
|
| + scope_->set_end_position(entry.end_pos());
|
| + Expect(Token::RBRACE, ok);
|
| + if (!*ok) {
|
| return;
|
| }
|
| + isolate()->counters()->total_preparse_skipped()->Increment(
|
| + scope_->end_position() - function_block_pos);
|
| + *materialized_literal_count = entry.literal_count();
|
| + *expected_property_count = entry.property_count();
|
| + scope_->SetStrictMode(entry.strict_mode());
|
| } else {
|
| // With no cached data, we partially parse the function, without building an
|
| // AST. This gathers the data needed to build a lazy function.
|
| @@ -3675,7 +3591,7 @@ void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
|
| *materialized_literal_count = logger.literals();
|
| *expected_property_count = logger.properties();
|
| scope_->SetStrictMode(logger.strict_mode());
|
| - if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
|
| + if (cached_data_mode() == PRODUCE_CACHED_DATA) {
|
| ASSERT(log_);
|
| // Position right after terminal '}'.
|
| int body_end = scanner()->location().end_pos;
|
| @@ -4767,70 +4683,6 @@ RegExpTree* RegExpParser::ParseCharacterClass() {
|
| // ----------------------------------------------------------------------------
|
| // The Parser interface.
|
|
|
| -ScriptData::~ScriptData() {
|
| - if (owns_store_) store_.Dispose();
|
| -}
|
| -
|
| -
|
| -int ScriptData::Length() {
|
| - return store_.length() * sizeof(unsigned);
|
| -}
|
| -
|
| -
|
| -const char* ScriptData::Data() {
|
| - return reinterpret_cast<const char*>(store_.start());
|
| -}
|
| -
|
| -
|
| -bool ScriptData::HasError() {
|
| - return has_error();
|
| -}
|
| -
|
| -
|
| -void ScriptData::Initialize() {
|
| - // Prepares state for use.
|
| - if (store_.length() >= PreparseDataConstants::kHeaderSize) {
|
| - function_index_ = PreparseDataConstants::kHeaderSize;
|
| - int symbol_data_offset = PreparseDataConstants::kHeaderSize
|
| - + store_[PreparseDataConstants::kFunctionsSizeOffset];
|
| - if (store_.length() > symbol_data_offset) {
|
| - symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
|
| - } else {
|
| - // Partial preparse causes no symbol information.
|
| - symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
|
| - }
|
| - symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
|
| - }
|
| -}
|
| -
|
| -
|
| -int ScriptData::ReadNumber(byte** source) {
|
| - // Reads a number from symbol_data_ in base 128. The most significant
|
| - // bit marks that there are more digits.
|
| - // If the first byte is 0x80 (kNumberTerminator), it would normally
|
| - // represent a leading zero. Since that is useless, and therefore won't
|
| - // appear as the first digit of any actual value, it is used to
|
| - // mark the end of the input stream.
|
| - byte* data = *source;
|
| - if (data >= symbol_data_end_) return -1;
|
| - byte input = *data;
|
| - if (input == PreparseDataConstants::kNumberTerminator) {
|
| - // End of stream marker.
|
| - return -1;
|
| - }
|
| - int result = input & 0x7f;
|
| - data++;
|
| - while ((input & 0x80u) != 0) {
|
| - if (data >= symbol_data_end_) return -1;
|
| - input = *data;
|
| - result = (result << 7) | (input & 0x7f);
|
| - data++;
|
| - }
|
| - *source = data;
|
| - return result;
|
| -}
|
| -
|
| -
|
| bool RegExpParser::ParseRegExp(FlatStringReader* input,
|
| bool multiline,
|
| RegExpCompileData* result,
|
| @@ -4877,7 +4729,7 @@ bool Parser::Parse() {
|
| result = ParseProgram();
|
| }
|
| } else {
|
| - SetCachedData(info()->cached_data(), info()->cached_data_mode());
|
| + SetCachedData();
|
| result = ParseProgram();
|
| }
|
| info()->SetFunction(result);
|
|
|