Commit ef99f666 authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Revert "[parser] Inital parallel parse tasks implementation."

This reverts commit 56a6fda3.

Reason for revert: Makes tsan flaky:
https://build.chromium.org/p/client.v8/builders/V8%20Linux64%20TSAN/builds/15038

Original change's description:
> [parser] Inital parallel parse tasks implementation.
> 
> While parsing top-level code eager functions are skipped just like lazy
> ones, but also a parse task is created for each.
> 
> The parse tasks are run by the compiler dispatcher and can be executed
> either on background thread or in idle time.
> After parsing of top-level code finishes it waits for all unfinished
> parser tasks - possibly picking up and executing them on current thread.
> Afterwards parse task results are stitched together with top-level AST,
> in case of failures eager functions are treated just like lazy -
> parsing/compilation is retriggered for them in the runtime and proper
> errors are generated (performance is not optimized for error case at
> all).
> 
> BUG=v8:6093
> 
> Change-Id: I718dd2acc8a70ae1b09c2dea2616716605d7b05d
> Reviewed-on: https://chromium-review.googlesource.com/483439
> Commit-Queue: Wiktor Garbacz <wiktorg@google.com>
> Reviewed-by: Marja Hölttä <marja@chromium.org>
> Reviewed-by: Jochen Eisinger <jochen@chromium.org>
> Reviewed-by: Daniel Vogelheim <vogelheim@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#44849}

TBR=marja@chromium.org,vogelheim@chromium.org,jochen@chromium.org,wiktorg@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:6093

Change-Id: I17e689efee7d216d28a94a5c8147022ae7e830dd
Reviewed-on: https://chromium-review.googlesource.com/486883Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44859}
parent a489abe8
......@@ -350,23 +350,6 @@ bool FunctionLiteral::NeedsHomeObject(Expression* expr) {
return expr->AsFunctionLiteral()->scope()->NeedsHomeObject();
}
void FunctionLiteral::ReplaceBodyAndScope(FunctionLiteral* other) {
DCHECK_NULL(body_);
DCHECK_NOT_NULL(scope_);
DCHECK_NOT_NULL(other->scope());
Scope* outer_scope = scope_->outer_scope();
body_ = other->body();
scope_ = other->scope();
scope_->ReplaceOuterScope(outer_scope);
#ifdef DEBUG
scope_->set_replaced_from_parse_task(true);
#endif
function_length_ = other->function_length_;
}
ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
Kind kind, bool is_computed_name)
: LiteralProperty(key, value, is_computed_name),
......
......@@ -2742,8 +2742,6 @@ class FunctionLiteral final : public Expression {
function_literal_id_ = function_literal_id;
}
void ReplaceBodyAndScope(FunctionLiteral* other);
private:
friend class AstNodeFactory;
......
......@@ -1799,9 +1799,7 @@ void Scope::CheckZones() {
DCHECK_NULL(scope->inner_scope_);
continue;
}
if (!scope->replaced_from_parse_task()) {
CHECK_EQ(scope->zone(), zone());
}
CHECK_EQ(scope->zone(), zone());
scope->CheckZones();
}
}
......
......@@ -456,11 +456,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// Check that all Scopes in the scope tree use the same Zone.
void CheckZones();
bool replaced_from_parse_task() const { return replaced_from_parse_task_; }
void set_replaced_from_parse_task(bool replaced_from_parse_task) {
replaced_from_parse_task_ = replaced_from_parse_task;
}
#endif
// Retrieve `IsSimpleParameterList` of current or outer function.
......@@ -540,10 +535,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
// True if this scope may contain objects from a temp zone that needs to be
// fixed up.
bool needs_migration_;
// True if scope comes from other zone - as a result of being created in a
// parse tasks.
bool replaced_from_parse_task_ = false;
#endif
// Source positions.
......
......@@ -43,7 +43,7 @@ enum class CompileJobStatus {
kDone,
};
class V8_EXPORT_PRIVATE CompileJobFinishCallback {
class CompileJobFinishCallback {
public:
virtual ~CompileJobFinishCallback() {}
virtual void ParseFinished(std::unique_ptr<ParseInfo> parse_info) = 0;
......
......@@ -248,6 +248,8 @@ CompilerDispatcher::~CompilerDispatcher() {
bool CompilerDispatcher::CanEnqueue() {
if (!IsEnabled()) return false;
DCHECK(FLAG_ignition);
if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) {
return false;
}
......@@ -261,8 +263,6 @@ bool CompilerDispatcher::CanEnqueue() {
}
bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
DCHECK_IMPLIES(IsEnabled(), FLAG_ignition);
if (!CanEnqueue()) return false;
// We only handle functions (no eval / top-level code / wasm) that are
......@@ -598,7 +598,7 @@ CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
void CompilerDispatcher::ScheduleIdleTaskFromAnyThread() {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
if (!platform_->IdleTasksEnabled(v8_isolate)) return;
DCHECK(platform_->IdleTasksEnabled(v8_isolate));
{
base::LockGuard<base::Mutex> lock(&mutex_);
if (idle_task_scheduled_) return;
......
......@@ -40,10 +40,7 @@ ParseInfo::ParseInfo(AccountingAllocator* zone_allocator)
function_name_(nullptr),
runtime_call_stats_(nullptr),
literal_(nullptr),
deferred_handles_(nullptr),
child_infos_(FLAG_use_parse_tasks
? new std::map<int, std::unique_ptr<ParseInfo>>()
: nullptr) {}
deferred_handles_(nullptr) {}
ParseInfo::ParseInfo(Handle<SharedFunctionInfo> shared)
: ParseInfo(shared->GetIsolate()->allocator()) {
......@@ -167,13 +164,6 @@ void ParseInfo::InitFromIsolate(Isolate* isolate) {
set_ast_string_constants(isolate->ast_string_constants());
}
void ParseInfo::ParseFinished(std::unique_ptr<ParseInfo> info) {
if (info->literal()) {
int start_position = info->literal()->start_position();
child_infos_->insert(std::make_pair(start_position, std::move(info)));
}
}
#ifdef DEBUG
bool ParseInfo::script_is_native() const {
return script_->type() == Script::TYPE_NATIVE;
......
......@@ -5,11 +5,9 @@
#ifndef V8_PARSING_PARSE_INFO_H_
#define V8_PARSING_PARSE_INFO_H_
#include <map>
#include <memory>
#include "include/v8.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/globals.h"
#include "src/handles.h"
#include "src/parsing/preparsed-scope-data.h"
......@@ -35,7 +33,7 @@ class Utf16CharacterStream;
class Zone;
// A container for the inputs, configuration options, and outputs of parsing.
class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
class V8_EXPORT_PRIVATE ParseInfo {
public:
explicit ParseInfo(AccountingAllocator* zone_allocator);
ParseInfo(Handle<Script> script);
......@@ -245,12 +243,6 @@ class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
}
}
const std::map<int, std::unique_ptr<ParseInfo>>* child_infos() const {
return child_infos_.get();
}
void ParseFinished(std::unique_ptr<ParseInfo> info) override;
#ifdef DEBUG
bool script_is_native() const;
#endif // DEBUG
......@@ -310,8 +302,6 @@ class V8_EXPORT_PRIVATE ParseInfo : public CompileJobFinishCallback {
//----------- Output of parsing and scope analysis ------------------------
FunctionLiteral* literal_;
std::shared_ptr<DeferredHandles> deferred_handles_;
// The key of the map is the FunctionLiteral's start_position
std::unique_ptr<std::map<int, std::unique_ptr<ParseInfo>>> child_infos_;
void SetFlag(Flag f) { flags_ |= f; }
void SetFlag(Flag f, bool v) { flags_ = v ? flags_ | f : flags_ & ~f; }
......
This diff is collapsed.
......@@ -273,8 +273,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
void SetCachedData(ParseInfo* info);
void StitchAst(ParseInfo* top_level_parse_info, Isolate* isolate);
ScriptCompiler::CompileOptions compile_options() const {
return compile_options_;
}
......@@ -1154,11 +1152,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
PreParser* reusable_preparser_;
Mode mode_;
std::vector<FunctionLiteral*> literals_to_stitch_;
Handle<String> source_;
CompilerDispatcher* compiler_dispatcher_ = nullptr;
ParseInfo* main_parse_info_ = nullptr;
friend class ParserTarget;
friend class ParserTargetScope;
ParserTarget* target_stack_; // for break, continue statements
......
......@@ -101,8 +101,10 @@ PreParserIdentifier PreParser::GetSymbol() const {
return symbol;
}
PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
PreParser::PreParseResult PreParser::PreParseProgram(bool is_module,
int* use_counts) {
DCHECK_NULL(scope_);
use_counts_ = use_counts;
DeclarationScope* scope = NewScriptScope();
#ifdef DEBUG
scope->set_is_being_lazily_parsed(true);
......@@ -121,6 +123,7 @@ PreParser::PreParseResult PreParser::PreParseProgram(bool is_module) {
PreParserStatementList body;
ParseStatementList(body, Token::EOS, &ok);
original_scope_ = nullptr;
use_counts_ = nullptr;
if (stack_overflow()) return kPreParseStackOverflow;
if (!ok) {
ReportUnexpectedToken(scanner()->current_token());
......@@ -286,6 +289,9 @@ 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);
......@@ -333,6 +339,22 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
}
if (FLAG_use_parse_tasks && is_top_level && preparse_data_) {
preparse_data_->AddFunctionData(
start_position, PreParseData::FunctionData(
end_position, formals.num_parameters(),
GetLastFunctionLiteralId() - func_id, language_mode,
function_scope->uses_super_property()));
// 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- %d inner-funcs\n", GetLastFunctionLiteralId() - func_id);
}
}
if (FLAG_experimental_preparser_scope_analysis &&
track_unresolved_variables_ && preparsed_scope_data_ != nullptr) {
preparsed_scope_data_->AddSkippableFunction(
......
......@@ -901,6 +901,7 @@ class PreParser : public ParserBase<PreParser> {
ast_value_factory, runtime_call_stats,
preparsed_scope_data, 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) {}
......@@ -912,7 +913,8 @@ 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);
PreParseResult PreParseProgram(bool is_module = false,
int* use_counts = nullptr);
// Parses a single function literal, from the opening parentheses before
// parameters to the closing brace after the body.
......@@ -928,6 +930,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
......@@ -1665,6 +1669,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_;
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --compiler-dispatcher --use-parse-tasks --use-external-strings
(function(a) {
assertEquals(a, "IIFE");
})("IIFE");
(function(a, ...rest) {
assertEquals(a, 1);
assertEquals(rest.length, 2);
assertEquals(rest[0], 2);
assertEquals(rest[1], 3);
})(1,2,3);
var outer_var = 42;
function lazy_outer() {
return 42;
}
var eager_outer = (function() { return 42; });
(function() {
assertEquals(outer_var, 42);
assertEquals(lazy_outer(), 42);
assertEquals(eager_outer(), 42);
})();
var gen = (function*() {
yield 1;
yield 2;
})();
assertEquals(gen.next().value, 1);
assertEquals(gen.next().value, 2);
var result = (function recursive(a=0) {
if (a == 1) {
return 42;
}
return recursive(1);
})();
assertEquals(result, 42);
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