[parser] Parse tasks: save top-level function data.
BUG=v8:6093 Change-Id: I7268abd56769d4cbaefdaa901c532871837cc47e Reviewed-on: https://chromium-review.googlesource.com/452340 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Wiktor Garbacz <wiktorg@google.com> Cr-Commit-Position: refs/heads/master@{#43782}
This commit is contained in:
parent
4c9ba86294
commit
15e23b13ed
@ -918,6 +918,10 @@ DEFINE_BOOL(trace_for_in_enumerate, false, "Trace for-in enumerate slow-paths")
|
||||
DEFINE_BOOL(trace_maps, false, "trace map creation")
|
||||
#endif
|
||||
|
||||
// preparser.cc
|
||||
DEFINE_BOOL(use_parse_tasks, false, "use parse tasks")
|
||||
DEFINE_BOOL(trace_parse_tasks, false, "trace parse task creation")
|
||||
|
||||
// parser.cc
|
||||
DEFINE_BOOL(allow_natives_syntax, false, "allow natives syntax")
|
||||
DEFINE_BOOL(trace_parse, false, "trace parsing and preparsing")
|
||||
|
@ -201,6 +201,7 @@ class ParserBase {
|
||||
RuntimeCallStats* runtime_call_stats,
|
||||
bool parsing_on_main_thread = true)
|
||||
: scope_(nullptr),
|
||||
original_scope_(nullptr),
|
||||
function_state_(nullptr),
|
||||
extension_(extension),
|
||||
fni_(nullptr),
|
||||
@ -1391,6 +1392,7 @@ class ParserBase {
|
||||
// Parser base's protected field members.
|
||||
|
||||
Scope* scope_; // Scope stack.
|
||||
Scope* original_scope_; // The top scope for the current parsing item.
|
||||
FunctionState* function_state_; // Function state stack.
|
||||
v8::Extension* extension_;
|
||||
FuncNameInferrer* fni_;
|
||||
|
@ -507,7 +507,6 @@ Parser::Parser(ParseInfo* info)
|
||||
true),
|
||||
scanner_(info->unicode_cache()),
|
||||
reusable_preparser_(nullptr),
|
||||
original_scope_(nullptr),
|
||||
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
|
||||
target_stack_(nullptr),
|
||||
compile_options_(info->compile_options()),
|
||||
@ -624,6 +623,12 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
|
||||
|
||||
{
|
||||
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source));
|
||||
if (FLAG_use_parse_tasks) {
|
||||
// FIXME(wiktorg) make it useful for something
|
||||
scanner_.Initialize(stream.get());
|
||||
reusable_preparser()->PreParseProgram();
|
||||
stream->Seek(0);
|
||||
}
|
||||
scanner_.Initialize(stream.get());
|
||||
result = DoParseProgram(info);
|
||||
}
|
||||
|
@ -1164,7 +1164,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
|
||||
Scanner scanner_;
|
||||
PreParser* reusable_preparser_;
|
||||
Scope* original_scope_; // for ES5 function declarations in sloppy eval
|
||||
Mode mode_;
|
||||
|
||||
friend class ParserTarget;
|
||||
|
@ -60,6 +60,24 @@ ScriptData* ParserLogger::GetScriptData() {
|
||||
return result;
|
||||
}
|
||||
|
||||
PreParseData::FunctionData PreParseData::GetTopLevelFunctionData(
|
||||
int start) const {
|
||||
auto it = top_level_functions_data_.find(start);
|
||||
if (it != top_level_functions_data_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return FunctionData();
|
||||
}
|
||||
|
||||
void PreParseData::AddTopLevelFunctionData(FunctionData&& data) {
|
||||
DCHECK(data.is_valid());
|
||||
top_level_functions_data_[data.start] = std::move(data);
|
||||
}
|
||||
|
||||
void PreParseData::AddTopLevelFunctionData(const FunctionData& data) {
|
||||
DCHECK(data.is_valid());
|
||||
top_level_functions_data_[data.start] = data;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8.
|
||||
|
@ -5,6 +5,8 @@
|
||||
#ifndef V8_PARSING_PREPARSE_DATA_H_
|
||||
#define V8_PARSING_PREPARSE_DATA_H_
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/allocation.h"
|
||||
#include "src/base/hashmap.h"
|
||||
#include "src/collector.h"
|
||||
@ -111,6 +113,40 @@ class ParserLogger final {
|
||||
#endif
|
||||
};
|
||||
|
||||
class PreParseData final {
|
||||
public:
|
||||
struct FunctionData {
|
||||
int start;
|
||||
int end;
|
||||
int num_parameters;
|
||||
int function_length;
|
||||
bool has_duplicate_parameters;
|
||||
int expected_property_count;
|
||||
int num_inner_functions;
|
||||
|
||||
FunctionData() : start(-1), end(-1) {}
|
||||
|
||||
FunctionData(int start, int end, int num_parameters, int function_length,
|
||||
bool has_duplicate_parameters, int expected_property_count,
|
||||
int num_inner_functions)
|
||||
: start(start),
|
||||
end(end),
|
||||
num_parameters(num_parameters),
|
||||
function_length(function_length),
|
||||
has_duplicate_parameters(has_duplicate_parameters),
|
||||
expected_property_count(expected_property_count),
|
||||
num_inner_functions(num_inner_functions) {}
|
||||
|
||||
bool is_valid() const { return start < end; }
|
||||
};
|
||||
|
||||
FunctionData GetTopLevelFunctionData(int start) const;
|
||||
void AddTopLevelFunctionData(FunctionData&& data);
|
||||
void AddTopLevelFunctionData(const FunctionData& data);
|
||||
|
||||
private:
|
||||
std::unordered_map<int, FunctionData> top_level_functions_data_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8.
|
||||
|
@ -85,6 +85,35 @@ PreParserIdentifier PreParser::GetSymbol() const {
|
||||
return symbol;
|
||||
}
|
||||
|
||||
PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
|
||||
DCHECK_NULL(scope_);
|
||||
DeclarationScope* scope = NewScriptScope();
|
||||
#ifdef DEBUG
|
||||
scope->set_is_being_lazily_parsed(true);
|
||||
#endif
|
||||
|
||||
// ModuleDeclarationInstantiation for Source Text Module Records creates a
|
||||
// new Module Environment Record whose outer lexical environment record is
|
||||
// the global scope.
|
||||
if (is_module) scope = NewModuleScope(scope);
|
||||
|
||||
FunctionState top_scope(&function_state_, &scope_, scope);
|
||||
original_scope_ = scope_;
|
||||
bool ok = true;
|
||||
int start_position = scanner()->peek_location().beg_pos;
|
||||
parsing_module_ = is_module;
|
||||
PreParserStatementList body;
|
||||
ParseStatementList(body, Token::EOS, &ok);
|
||||
original_scope_ = nullptr;
|
||||
if (stack_overflow()) return kPreParseStackOverflow;
|
||||
if (!ok) {
|
||||
ReportUnexpectedToken(scanner()->current_token());
|
||||
} else if (is_strict(this->scope()->language_mode())) {
|
||||
CheckStrictOctalLiteral(start_position, scanner()->location().end_pos, &ok);
|
||||
}
|
||||
return kPreParseSuccess;
|
||||
}
|
||||
|
||||
PreParser::PreParseResult PreParser::PreParseFunction(
|
||||
FunctionKind kind, DeclarationScope* function_scope, bool parsing_module,
|
||||
bool is_inner_function, bool may_abort, int* use_counts) {
|
||||
@ -233,12 +262,15 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
||||
runtime_call_stats_,
|
||||
counters[track_unresolved_variables_][parsing_on_main_thread_]);
|
||||
|
||||
bool is_top_level =
|
||||
scope()->AllowsLazyParsingWithoutUnresolvedVariables(original_scope_);
|
||||
|
||||
DeclarationScope* function_scope = NewFunctionScope(kind);
|
||||
function_scope->SetLanguageMode(language_mode);
|
||||
FunctionState function_state(&function_state_, &scope_, function_scope);
|
||||
DuplicateFinder duplicate_finder;
|
||||
ExpressionClassifier formals_classifier(this, &duplicate_finder);
|
||||
GetNextFunctionLiteralId();
|
||||
int func_id = GetNextFunctionLiteralId();
|
||||
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
int start_position = scanner()->location().beg_pos;
|
||||
@ -280,6 +312,30 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
|
||||
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
|
||||
}
|
||||
|
||||
if (FLAG_use_parse_tasks && is_top_level && preparse_data_) {
|
||||
preparse_data_->AddTopLevelFunctionData(PreParseData::FunctionData(
|
||||
start_position, end_position, formals.num_parameters(),
|
||||
formals.function_length,
|
||||
formals_classifier.is_valid_formal_parameter_list_without_duplicates(),
|
||||
function_state_->expected_property_count(),
|
||||
GetLastFunctionLiteralId() - func_id));
|
||||
// TODO(wiktorg) spin-off a parse task
|
||||
if (FLAG_trace_parse_tasks) {
|
||||
PrintF("Saved function at %d to %d with:\n", start_position,
|
||||
end_position);
|
||||
PrintF("\t- %d params\n", formals.num_parameters());
|
||||
PrintF("\t- %d function length\n", formals.function_length);
|
||||
PrintF(
|
||||
"\t- %s duplicate parameters\n",
|
||||
formals_classifier.is_valid_formal_parameter_list_without_duplicates()
|
||||
? "NO"
|
||||
: "SOME");
|
||||
PrintF("\t- %d expected properties\n",
|
||||
function_state_->expected_property_count());
|
||||
PrintF("\t- %d inner-funcs\n", GetLastFunctionLiteralId() - func_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_trace_preparse) {
|
||||
PrintF(" [%s]: %i-%i\n",
|
||||
track_unresolved_variables_ ? "Preparse resolution"
|
||||
|
@ -888,6 +888,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
ast_value_factory, runtime_call_stats,
|
||||
parsing_on_main_thread),
|
||||
use_counts_(nullptr),
|
||||
preparse_data_(FLAG_use_parse_tasks ? new PreParseData() : nullptr),
|
||||
track_unresolved_variables_(false),
|
||||
pending_error_handler_(pending_error_handler) {}
|
||||
|
||||
@ -899,33 +900,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
// success (even if parsing failed, the pre-parse data successfully
|
||||
// captured the syntax error), and false if a stack-overflow happened
|
||||
// during parsing.
|
||||
PreParseResult PreParseProgram(bool is_module = false) {
|
||||
DCHECK_NULL(scope_);
|
||||
DeclarationScope* scope = NewScriptScope();
|
||||
#ifdef DEBUG
|
||||
scope->set_is_being_lazily_parsed(true);
|
||||
#endif
|
||||
|
||||
// ModuleDeclarationInstantiation for Source Text Module Records creates a
|
||||
// new Module Environment Record whose outer lexical environment record is
|
||||
// the global scope.
|
||||
if (is_module) scope = NewModuleScope(scope);
|
||||
|
||||
FunctionState top_scope(&function_state_, &scope_, scope);
|
||||
bool ok = true;
|
||||
int start_position = scanner()->peek_location().beg_pos;
|
||||
parsing_module_ = is_module;
|
||||
PreParserStatementList body;
|
||||
ParseStatementList(body, Token::EOS, &ok);
|
||||
if (stack_overflow()) return kPreParseStackOverflow;
|
||||
if (!ok) {
|
||||
ReportUnexpectedToken(scanner()->current_token());
|
||||
} else if (is_strict(this->scope()->language_mode())) {
|
||||
CheckStrictOctalLiteral(start_position, scanner()->location().end_pos,
|
||||
&ok);
|
||||
}
|
||||
return kPreParseSuccess;
|
||||
}
|
||||
PreParseResult PreParseProgram(bool is_module = false);
|
||||
|
||||
// Parses a single function literal, from the opening parentheses before
|
||||
// parameters to the closing brace after the body.
|
||||
@ -941,6 +916,8 @@ class PreParser : public ParserBase<PreParser> {
|
||||
bool track_unresolved_variables,
|
||||
bool may_abort, int* use_counts);
|
||||
|
||||
const PreParseData* preparse_data() const { return preparse_data_.get(); }
|
||||
|
||||
private:
|
||||
// These types form an algebra over syntactic categories that is just
|
||||
// rich enough to let us recognize and propagate the constructs that
|
||||
@ -1679,6 +1656,7 @@ class PreParser : public ParserBase<PreParser> {
|
||||
// Preparser's private field members.
|
||||
|
||||
int* use_counts_;
|
||||
std::unique_ptr<PreParseData> preparse_data_;
|
||||
bool track_unresolved_variables_;
|
||||
PreParserLogger log_;
|
||||
PendingCompilationErrorHandler* pending_error_handler_;
|
||||
|
Loading…
Reference in New Issue
Block a user