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); |