Commit 15e23b13 authored by Wiktor Garbacz's avatar Wiktor Garbacz Committed by Commit Bot

[parser] Parse tasks: save top-level function data.

BUG=v8:6093

Change-Id: I7268abd56769d4cbaefdaa901c532871837cc47e
Reviewed-on: https://chromium-review.googlesource.com/452340Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Wiktor Garbacz <wiktorg@google.com>
Cr-Commit-Position: refs/heads/master@{#43782}
parent 4c9ba862
......@@ -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_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment