Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(747)

Unified Diff: src/parser.cc

Issue 376223002: Refactor ScriptData class for cached compile data. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/preparse-data.h » ('j') | src/preparse-data.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « src/parser.h ('k') | src/preparse-data.h » ('j') | src/preparse-data.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698