Commit 67154399 authored by machenbach's avatar machenbach Committed by Commit bot

Revert of [complier] Enable parallel eager inner function compilation with...

Revert of [complier] Enable parallel eager inner function compilation with compiler dispatcher. (patchset #11 id:260001 of https://codereview.chromium.org/2611313002/ )

Reason for revert:
Some crashes on mac:
https://build.chromium.org/p/client.v8/builders/V8%20Mac%20-%20debug/builds/11982/steps/Ignition%20-%20turbofan/logs/regress-crbug-429159
https://build.chromium.org/p/client.v8/builders/V8%20Mac%20GC%20Stress/builds/10966

Original issue's description:
> [complier] Enable parallel eager inner function compilation with compiler dispatcher.
>
> Enable enqueueing of eager inner function compilation onto the compiler
> dispatcher. This enables these tasks to be performed in parallel to
> compilation of the outer functio (only for Ignition functions).
> We currently synchronize to ensure all inner function compilations
>  are complete before executing the outer function - future work will
> allow outer function execution to happenin parallel to inner function
> compilation.
>
> BUG=v8:5203,v8:5215
>
> Review-Url: https://codereview.chromium.org/2611313002
> Cr-Commit-Position: refs/heads/master@{#42413}
> Committed: https://chromium.googlesource.com/v8/v8/+/f12661a1ece4e9c9cb8df5c2d349db960356e604

TBR=jochen@chromium.org,marja@chromium.org,mstarzinger@chromium.org,rmcilroy@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:5203,v8:5215

Review-Url: https://codereview.chromium.org/2637123002
Cr-Commit-Position: refs/heads/master@{#42416}
parent 29aaefa1
......@@ -66,8 +66,7 @@ CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size)
: status_(CompileJobStatus::kInitial),
isolate_(isolate),
: isolate_(isolate),
tracer_(tracer),
shared_(Handle<SharedFunctionInfo>::cast(
isolate_->global_handles()->Create(*shared))),
......@@ -80,35 +79,7 @@ CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
shared_->ShortPrint();
PrintF(" in initial state.\n");
}
}
CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate,
CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
FunctionLiteral* literal,
size_t max_stack_size)
: status_(CompileJobStatus::kAnalyzed),
isolate_(isolate),
tracer_(tracer),
shared_(Handle<SharedFunctionInfo>::cast(
isolate_->global_handles()->Create(*shared))),
max_stack_size_(max_stack_size),
zone_(new Zone(isolate->allocator(), ZONE_NAME)),
parse_info_(new ParseInfo(
zone_.get(), Handle<Script>(Script::cast(shared->script())))),
compile_info_(
new CompilationInfo(parse_info_.get(), Handle<JSFunction>::null())),
trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) {
parse_info_->set_literal(literal);
parse_info_->set_shared_info(shared);
parse_info_->set_function_literal_id(shared->function_literal_id());
parse_info_->set_language_mode(literal->scope()->language_mode());
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this));
shared_->ShortPrint();
PrintF(" in Analyzed state.\n");
PrintF("\n");
}
}
......@@ -281,7 +252,7 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
if (parse_info_->literal() == nullptr) {
status_ = CompileJobStatus::kFailed;
} else {
status_ = CompileJobStatus::kReadyToAnalyze;
status_ = CompileJobStatus::kReadyToAnalyse;
}
DeferredHandleScope scope(isolate_);
......@@ -312,38 +283,25 @@ bool CompilerDispatcherJob::FinalizeParsingOnMainThread() {
return status_ != CompileJobStatus::kFailed;
}
bool CompilerDispatcherJob::AnalyzeOnMainThread() {
bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kReadyToAnalyze);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kAnalyze);
DCHECK(status() == CompileJobStatus::kReadyToAnalyse);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
if (trace_compiler_dispatcher_jobs_) {
PrintF("CompilerDispatcherJob[%p]: Analyzing\n", static_cast<void*>(this));
PrintF("CompilerDispatcherJob[%p]: Preparing to compile\n",
static_cast<void*>(this));
}
compile_info_.reset(
new CompilationInfo(parse_info_.get(), Handle<JSFunction>::null()));
DeferredHandleScope scope(isolate_);
{
if (Compiler::Analyze(parse_info_.get())) {
status_ = CompileJobStatus::kAnalyzed;
} else {
status_ = CompileJobStatus::kFailed;
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
}
if (Compiler::Analyze(parse_info_.get())) {
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
}
compile_info_->set_deferred_handles(scope.Detach());
return status_ != CompileJobStatus::kFailed;
}
bool CompilerDispatcherJob::PrepareToCompileOnMainThread() {
DCHECK(ThreadId::Current().Equals(isolate_->thread_id()));
DCHECK(status() == CompileJobStatus::kAnalyzed);
COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile);
compile_job_.reset(
Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get()));
if (!compile_job_.get()) {
if (!isolate_->has_pending_exception()) isolate_->StackOverflow();
status_ = CompileJobStatus::kFailed;
......@@ -443,10 +401,7 @@ double CompilerDispatcherJob::EstimateRuntimeOfNextStepInMs() const {
case CompileJobStatus::kParsed:
return tracer_->EstimateFinalizeParsingInMs();
case CompileJobStatus::kReadyToAnalyze:
return tracer_->EstimateAnalyzeInMs();
case CompileJobStatus::kAnalyzed:
case CompileJobStatus::kReadyToAnalyse:
return tracer_->EstimatePrepareToCompileInMs();
case CompileJobStatus::kReadyToCompile:
......
......@@ -16,11 +16,9 @@
namespace v8 {
namespace internal {
class AstValueFactory;
class CompilerDispatcherTracer;
class CompilationInfo;
class CompilationJob;
class FunctionLiteral;
class Isolate;
class ParseInfo;
class Parser;
......@@ -34,8 +32,7 @@ enum class CompileJobStatus {
kInitial,
kReadyToParse,
kParsed,
kReadyToAnalyze,
kAnalyzed,
kReadyToAnalyse,
kReadyToCompile,
kCompiled,
kFailed,
......@@ -44,14 +41,9 @@ enum class CompileJobStatus {
class V8_EXPORT_PRIVATE CompilerDispatcherJob {
public:
// Creates a CompilerDispatcherJob in the initial state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
size_t max_stack_size);
// Creates a CompilerDispatcherJob in the analyzed state.
CompilerDispatcherJob(Isolate* isolate, CompilerDispatcherTracer* tracer,
Handle<SharedFunctionInfo> shared,
FunctionLiteral* literal, size_t max_stack_size);
~CompilerDispatcherJob();
CompileJobStatus status() const { return status_; }
......@@ -66,15 +58,11 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
// Transition from kReadyToParse to kParsed.
void Parse();
// Transition from kParsed to kReadyToAnalyze (or kFailed). Returns false
// Transition from kParsed to kReadyToAnalyse (or kFailed). Returns false
// when transitioning to kFailed. In that case, an exception is pending.
bool FinalizeParsingOnMainThread();
// Transition from kReadyToAnalyze to kAnalyzed (or kFailed). Returns
// false when transitioning to kFailed. In that case, an exception is pending.
bool AnalyzeOnMainThread();
// Transition from kAnalyzed to kReadyToCompile (or kFailed). Returns
// Transition from kReadyToAnalyse to kReadyToCompile (or kFailed). Returns
// false when transitioning to kFailed. In that case, an exception is pending.
bool PrepareToCompileOnMainThread();
......@@ -98,7 +86,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcherJob {
private:
FRIEND_TEST(CompilerDispatcherJobTest, ScopeChain);
CompileJobStatus status_;
CompileJobStatus status_ = CompileJobStatus::kInitial;
Isolate* isolate_;
CompilerDispatcherTracer* tracer_;
Handle<SharedFunctionInfo> shared_; // Global handle.
......
......@@ -39,9 +39,6 @@ CompilerDispatcherTracer::Scope::~Scope() {
case ScopeID::kFinalizeParsing:
tracer_->RecordFinalizeParsing(elapsed);
break;
case ScopeID::kAnalyze:
tracer_->RecordAnalyze(elapsed);
break;
case ScopeID::kPrepareToCompile:
tracer_->RecordPrepareToCompile(elapsed);
break;
......@@ -63,8 +60,6 @@ const char* CompilerDispatcherTracer::Scope::Name(ScopeID scope_id) {
return "V8.BackgroundCompile_Parse";
case ScopeID::kFinalizeParsing:
return "V8.BackgroundCompile_FinalizeParsing";
case ScopeID::kAnalyze:
return "V8.BackgroundCompile_Analyze";
case ScopeID::kPrepareToCompile:
return "V8.BackgroundCompile_PrepareToCompile";
case ScopeID::kCompile:
......@@ -102,11 +97,6 @@ void CompilerDispatcherTracer::RecordFinalizeParsing(double duration_ms) {
finalize_parsing_events_.Push(duration_ms);
}
void CompilerDispatcherTracer::RecordAnalyze(double duration_ms) {
base::LockGuard<base::Mutex> lock(&mutex_);
analyze_events_.Push(duration_ms);
}
void CompilerDispatcherTracer::RecordPrepareToCompile(double duration_ms) {
base::LockGuard<base::Mutex> lock(&mutex_);
prepare_compile_events_.Push(duration_ms);
......@@ -138,11 +128,6 @@ double CompilerDispatcherTracer::EstimateFinalizeParsingInMs() const {
return Average(finalize_parsing_events_);
}
double CompilerDispatcherTracer::EstimateAnalyzeInMs() const {
base::LockGuard<base::Mutex> lock(&mutex_);
return Average(analyze_events_);
}
double CompilerDispatcherTracer::EstimatePrepareToCompileInMs() const {
base::LockGuard<base::Mutex> lock(&mutex_);
return Average(prepare_compile_events_);
......@@ -163,12 +148,11 @@ void CompilerDispatcherTracer::DumpStatistics() const {
PrintF(
"CompilerDispatcherTracer: "
"prepare_parsing=%.2lfms parsing=%.2lfms/kb finalize_parsing=%.2lfms "
"analyze=%.2lfms prepare_compiling=%.2lfms compiling=%.2lfms/kb "
"finalize_compiling=%.2lfms\n",
"prepare_compiling=%.2lfms compiling=%.2lfms/kb "
"finalize_compilig=%.2lfms\n",
EstimatePrepareToParseInMs(), EstimateParseInMs(1 * KB),
EstimateFinalizeParsingInMs(), EstimateAnalyzeInMs(),
EstimatePrepareToCompileInMs(), EstimateCompileInMs(1 * KB),
EstimateFinalizeCompilingInMs());
EstimateFinalizeParsingInMs(), EstimatePrepareToCompileInMs(),
EstimateCompileInMs(1 * KB), EstimateFinalizeCompilingInMs());
}
double CompilerDispatcherTracer::Average(
......
......@@ -35,7 +35,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherTracer {
kPrepareToParse,
kParse,
kFinalizeParsing,
kAnalyze,
kPrepareToCompile,
kCompile,
kFinalizeCompiling
......@@ -63,7 +62,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherTracer {
void RecordPrepareToParse(double duration_ms);
void RecordParse(double duration_ms, size_t source_length);
void RecordFinalizeParsing(double duration_ms);
void RecordAnalyze(double duration_ms);
void RecordPrepareToCompile(double duration_ms);
void RecordCompile(double duration_ms, size_t ast_size_in_bytes);
void RecordFinalizeCompiling(double duration_ms);
......@@ -71,7 +69,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherTracer {
double EstimatePrepareToParseInMs() const;
double EstimateParseInMs(size_t source_length) const;
double EstimateFinalizeParsingInMs() const;
double EstimateAnalyzeInMs() const;
double EstimatePrepareToCompileInMs() const;
double EstimateCompileInMs(size_t ast_size_in_bytes) const;
double EstimateFinalizeCompilingInMs() const;
......@@ -87,7 +84,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcherTracer {
base::RingBuffer<double> prepare_parse_events_;
base::RingBuffer<std::pair<size_t, double>> parse_events_;
base::RingBuffer<double> finalize_parsing_events_;
base::RingBuffer<double> analyze_events_;
base::RingBuffer<double> prepare_compile_events_;
base::RingBuffer<std::pair<size_t, double>> compile_events_;
base::RingBuffer<double> finalize_compiling_events_;
......
......@@ -8,7 +8,6 @@
#include "include/v8.h"
#include "src/base/platform/time.h"
#include "src/cancelable-task.h"
#include "src/compilation-info.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/flags.h"
......@@ -37,11 +36,7 @@ bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
job->FinalizeParsingOnMainThread();
break;
case CompileJobStatus::kReadyToAnalyze:
job->AnalyzeOnMainThread();
break;
case CompileJobStatus::kAnalyzed:
case CompileJobStatus::kReadyToAnalyse:
job->PrepareToCompileOnMainThread();
break;
......@@ -229,7 +224,7 @@ CompilerDispatcher::~CompilerDispatcher() {
task_manager_->CancelAndWait();
}
bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
if (!IsEnabled()) return false;
DCHECK(FLAG_ignition);
......@@ -250,17 +245,12 @@ bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
return false;
}
return true;
}
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
if (!CanEnqueue(function)) return false;
if (IsEnqueued(function)) return true;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: enqueuing ");
function->ShortPrint();
PrintF(" for parse and compile\n");
PrintF("\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
......@@ -287,44 +277,11 @@ bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) {
return true;
}
bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function,
FunctionLiteral* literal) {
if (!CanEnqueue(function)) return false;
if (IsEnqueued(function)) return true;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: enqueuing ");
function->ShortPrint();
PrintF(" for compile\n");
}
std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
isolate_, tracer_.get(), function, literal, max_stack_size_));
std::pair<int, int> key(Script::cast(function->script())->id(),
function->function_literal_id());
jobs_.insert(std::make_pair(key, std::move(job)));
ScheduleIdleTaskIfNeeded();
return true;
}
bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function,
FunctionLiteral* literal) {
if (!Enqueue(function, literal)) return false;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: stepping ");
function->ShortPrint();
PrintF("\n");
}
JobMap::const_iterator job = GetJobFor(function);
DoNextStepOnMainThread(isolate_, job->second.get(),
ExceptionHandling::kSwallow);
ConsiderJobForBackgroundProcessing(job->second.get());
return true;
bool CompilerDispatcher::IsEnabled() const {
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
return FLAG_compiler_dispatcher && platform_->IdleTasksEnabled(v8_isolate);
}
bool CompilerDispatcher::IsEnabled() const { return FLAG_compiler_dispatcher; }
bool CompilerDispatcher::IsEnqueued(Handle<SharedFunctionInfo> function) const {
return GetJobFor(function) != jobs_.end();
}
......@@ -345,16 +302,6 @@ void CompilerDispatcher::WaitForJobIfRunningOnBackground(
DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end());
}
bool CompilerDispatcher::FinishNow(CompilerDispatcherJob* job) {
WaitForJobIfRunningOnBackground(job);
while (!IsFinished(job)) {
DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow);
}
bool result = job->status() != CompileJobStatus::kFailed;
job->ResetOnMainThread();
return result;
}
bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
JobMap::const_iterator job = GetJobFor(function);
CHECK(job != jobs_.end());
......@@ -365,7 +312,12 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
PrintF(" now\n");
}
bool result = FinishNow(job->second.get());
WaitForJobIfRunningOnBackground(job->second.get());
while (!IsFinished(job->second.get())) {
DoNextStepOnMainThread(isolate_, job->second.get(),
ExceptionHandling::kThrow);
}
bool result = job->second->status() != CompileJobStatus::kFailed;
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: finished working on ");
......@@ -374,6 +326,7 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
tracer_->DumpStatistics();
}
job->second->ResetOnMainThread();
jobs_.erase(job);
if (jobs_.empty()) {
base::LockGuard<base::Mutex> lock(&mutex_);
......@@ -382,30 +335,6 @@ bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
return result;
}
bool CompilerDispatcher::FinishAllNow() {
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: finishing all jobs now\n");
}
bool result = true;
for (auto& it : jobs_) {
result &= FinishNow(it.second.get());
}
if (trace_compiler_dispatcher_) {
PrintF("CompilerDispatcher: finished all jobs\n");
}
jobs_.clear();
{
base::LockGuard<base::Mutex> lock(&mutex_);
DCHECK(pending_background_jobs_.empty());
DCHECK(running_background_jobs_.empty());
abort_ = false;
}
return result;
}
void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
bool background_tasks_running =
task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning;
......
......@@ -28,7 +28,6 @@ namespace internal {
class CancelableTaskManager;
class CompilerDispatcherJob;
class CompilerDispatcherTracer;
class FunctionLiteral;
class Isolate;
class SharedFunctionInfo;
......@@ -69,10 +68,7 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
size_t max_stack_size);
~CompilerDispatcher();
// Returns true if the compiler dispatcher is enabled.
bool IsEnabled() const;
// Enqueue a job for parse and compile. Returns true if a job was enqueued.
// Returns true if a job was enqueued.
bool Enqueue(Handle<SharedFunctionInfo> function);
// Like Enqueue, but also advances the job so that it can potentially
......@@ -80,27 +76,13 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
// true if the job was enqueued.
bool EnqueueAndStep(Handle<SharedFunctionInfo> function);
// Enqueue a job for compilation. Function must have already been parsed and
// analyzed and be ready for compilation. Returns true if a job was enqueued.
bool Enqueue(Handle<SharedFunctionInfo> function, FunctionLiteral* literal);
// Like Enqueue, but also advances the job so that it can potentially
// continue running on a background thread (if at all possible). Returns
// true if the job was enqueued.
bool EnqueueAndStep(Handle<SharedFunctionInfo> function,
FunctionLiteral* literal);
// Returns true if there is a pending job for the given function.
bool IsEnqueued(Handle<SharedFunctionInfo> function) const;
// Blocks until the given function is compiled (and does so as fast as
// possible). Returns true if the compile job was successful.
// possible). Returns true if the compile job was succesful.
bool FinishNow(Handle<SharedFunctionInfo> function);
// Blocks until all enqueued jobs have finished. Returns true if all the
// compile jobs were successful.
bool FinishAllNow();
// Aborts a given job. Blocks if requested.
void Abort(Handle<SharedFunctionInfo> function, BlockingBehavior blocking);
......@@ -113,8 +95,6 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
private:
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStep);
FRIEND_TEST(CompilerDispatcherTest, EnqueueParsed);
FRIEND_TEST(CompilerDispatcherTest, EnqueueAndStepParsed);
FRIEND_TEST(CompilerDispatcherTest, IdleTaskSmallIdleTime);
FRIEND_TEST(CompilerDispatcherTest, CompileOnBackgroundThread);
FRIEND_TEST(CompilerDispatcherTest, FinishNowWithBackgroundTask);
......@@ -130,10 +110,9 @@ class V8_EXPORT_PRIVATE CompilerDispatcher {
class IdleTask;
void WaitForJobIfRunningOnBackground(CompilerDispatcherJob* job);
bool IsEnabled() const;
void AbortInactiveJobs();
bool CanEnqueue(Handle<SharedFunctionInfo> function);
JobMap::const_iterator GetJobFor(Handle<SharedFunctionInfo> shared) const;
bool FinishNow(CompilerDispatcherJob* job);
void ConsiderJobForBackgroundProcessing(CompilerDispatcherJob* job);
void ScheduleMoreBackgroundTasksIfNeeded();
void ScheduleIdleTaskFromAnyThread();
......
......@@ -15,7 +15,6 @@
#include "src/bootstrapper.h"
#include "src/codegen.h"
#include "src/compilation-cache.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
#include "src/compiler/pipeline.h"
#include "src/crankshaft/hydrogen.h"
......@@ -376,20 +375,6 @@ bool ShouldUseIgnition(CompilationInfo* info) {
return shared->PassesFilter(FLAG_ignition_filter);
}
bool UseAsmWasm(DeclarationScope* scope, Handle<SharedFunctionInfo> shared_info,
bool is_debug) {
return FLAG_validate_asm && scope->asm_module() &&
!shared_info->is_asm_wasm_broken() && !is_debug;
}
bool UseCompilerDispatcher(CompilerDispatcher* dispatcher,
DeclarationScope* scope,
Handle<SharedFunctionInfo> shared_info,
bool is_debug, bool will_serialize) {
return dispatcher->IsEnabled() && !is_debug && !will_serialize &&
!UseAsmWasm(scope, shared_info, is_debug);
}
CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) {
// Function should have been parsed and analyzed before creating a compilation
// job.
......@@ -442,34 +427,30 @@ void InstallUnoptimizedCode(CompilationInfo* info) {
CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
CompilationJob::Status status = job->FinalizeJob();
if (status == CompilationJob::SUCCEEDED) {
CompilationInfo* info = job->info();
EnsureFeedbackMetadata(info);
DCHECK(!info->code().is_null());
if (info->parse_info()->literal()->should_be_used_once_hint()) {
info->code()->MarkToBeExecutedOnce(info->isolate());
}
InstallUnoptimizedCode(info);
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, info);
EnsureFeedbackMetadata(job->info());
InstallUnoptimizedCode(job->info());
job->RecordUnoptimizedCompilationStats();
}
return status;
}
bool Renumber(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
Handle<SharedFunctionInfo> shared_info,
bool Renumber(ParseInfo* parse_info,
Compiler::EagerInnerFunctionLiterals* eager_literals) {
RuntimeCallTimerScope runtimeTimer(isolate,
RuntimeCallTimerScope runtimeTimer(parse_info->isolate(),
&RuntimeCallStats::CompileRenumber);
if (!AstNumbering::Renumber(isolate->stack_guard()->real_climit(), zone,
literal, eager_literals)) {
if (!AstNumbering::Renumber(
parse_info->isolate()->stack_guard()->real_climit(),
parse_info->zone(), parse_info->literal(), eager_literals)) {
return false;
}
Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
if (!shared_info.is_null()) {
shared_info->set_ast_node_count(literal->ast_node_count());
if (literal->dont_optimize_reason() != kNoReason) {
shared_info->DisableOptimization(literal->dont_optimize_reason());
FunctionLiteral* lit = parse_info->literal();
shared_info->set_ast_node_count(lit->ast_node_count());
if (lit->dont_optimize_reason() != kNoReason) {
shared_info->DisableOptimization(lit->dont_optimize_reason());
}
if (literal->flags() & AstProperties::kMustUseIgnitionTurbo) {
if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) {
shared_info->set_must_use_ignition_turbo(true);
}
}
......@@ -477,7 +458,8 @@ bool Renumber(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
}
bool GenerateUnoptimizedCode(CompilationInfo* info) {
if (UseAsmWasm(info->scope(), info->shared_info(), info->is_debug())) {
if (FLAG_validate_asm && info->scope()->asm_module() &&
!info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) {
EnsureFeedbackMetadata(info);
MaybeHandle<FixedArray> wasm_data;
wasm_data = AsmJs::CompileAsmViaWasm(info);
......@@ -504,54 +486,54 @@ bool CompileUnoptimizedInnerFunctionsRecursively(
CompilationInfo* outer_info) {
Isolate* isolate = outer_info->isolate();
Handle<Script> script = outer_info->script();
bool is_debug = outer_info->is_debug();
bool will_serialize = outer_info->will_serialize();
RuntimeCallTimerScope runtimeTimer(isolate,
&RuntimeCallStats::CompileInnerFunction);
for (auto it : *literals) {
FunctionLiteral* literal = it->value();
Handle<SharedFunctionInfo> shared =
Compiler::GetSharedFunctionInfo(literal, script, outer_info);
if (shared->is_compiled()) continue;
// Find any previously allocated shared function info for the given literal.
Handle<SharedFunctionInfo> shared;
MaybeHandle<SharedFunctionInfo> maybe_existing =
script->FindSharedFunctionInfo(isolate, literal);
if (maybe_existing.ToHandle(&shared)) {
DCHECK(!shared->is_toplevel());
// If we found an existing shared function info with compiled code,
// we are done.
if (shared->is_compiled()) continue;
} else {
shared =
isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
shared->set_is_toplevel(false);
}
Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
parse_info.set_literal(literal);
parse_info.set_shared_info(shared);
parse_info.set_function_literal_id(shared->function_literal_id());
parse_info.set_language_mode(literal->scope()->language_mode());
parse_info.set_ast_value_factory(
outer_info->parse_info()->ast_value_factory());
parse_info.set_ast_value_factory_owned(false);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
if (outer_info->will_serialize()) info.PrepareForSerializing();
if (outer_info->is_debug()) info.MarkAsDebug();
Compiler::EagerInnerFunctionLiterals inner_literals;
if (!Renumber(isolate, outer_info->zone(), literal, shared,
&inner_literals) ||
if (!Renumber(&parse_info, &inner_literals) ||
!CompileUnoptimizedInnerFunctionsRecursively(&inner_literals,
outer_info)) {
outer_info) ||
!GenerateUnoptimizedCode(&info)) {
if (!isolate->has_pending_exception()) isolate->StackOverflow();
return false;
}
// Try to enqueue the eager function on the compiler dispatcher.
CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
if (UseCompilerDispatcher(dispatcher, literal->scope(), shared, is_debug,
will_serialize) &&
dispatcher->EnqueueAndStep(shared, literal)) {
// If we have successfully queued up the function for compilation on the
// compiler dispatcher then we are done.
continue;
} else {
// Otherwise generate unoptimized code now.
Zone zone(isolate->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, script);
CompilationInfo info(&parse_info, Handle<JSFunction>::null());
parse_info.set_literal(literal);
parse_info.set_shared_info(shared);
parse_info.set_function_literal_id(shared->function_literal_id());
parse_info.set_language_mode(literal->scope()->language_mode());
parse_info.set_ast_value_factory(
outer_info->parse_info()->ast_value_factory());
parse_info.set_ast_value_factory_owned(false);
if (will_serialize) info.PrepareForSerializing();
if (is_debug) info.MarkAsDebug();
if (!GenerateUnoptimizedCode(&info)) {
if (!isolate->has_pending_exception()) isolate->StackOverflow();
return false;
}
DCHECK(!info.code().is_null());
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info);
if (literal->should_be_used_once_hint()) {
info.code()->MarkToBeExecutedOnce(isolate);
}
}
return true;
......@@ -569,15 +551,6 @@ bool CompileUnoptimizedCode(CompilationInfo* info) {
return false;
}
// TODO(rmcilroy): Remove this once the enqueued tasks can keep the parsed
// zone and handles alive and replace with a check in CompileLazy to finish
// the task itself.
if (isolate->compiler_dispatcher()->IsEnabled() &&
!isolate->compiler_dispatcher()->FinishAllNow()) {
if (!isolate->has_pending_exception()) isolate->StackOverflow();
return false;
}
return true;
}
......@@ -1153,10 +1126,7 @@ bool Compiler::Analyze(ParseInfo* info,
&RuntimeCallStats::CompileAnalyse);
if (!Rewriter::Rewrite(info)) return false;
DeclarationScope::Analyze(info, AnalyzeMode::kRegular);
if (!Renumber(info->isolate(), info->zone(), info->literal(),
info->shared_info(), eager_literals)) {
return false;
}
if (!Renumber(info, eager_literals)) return false;
DCHECK_NOT_NULL(info->scope());
return true;
}
......@@ -1763,8 +1733,13 @@ bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
return FinalizeOptimizedCompilationJob(job.get()) ==
CompilationJob::SUCCEEDED;
} else {
return FinalizeUnoptimizedCompilationJob(job.get()) ==
CompilationJob::SUCCEEDED;
if (FinalizeUnoptimizedCompilationJob(job.get()) ==
CompilationJob::SUCCEEDED) {
RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
job->info());
return true;
}
return false;
}
}
......
......@@ -37,7 +37,7 @@ class ThreadedListZoneEntry;
// parameters which then can be executed. If the source code contains other
// functions, they might be compiled and allocated as part of the compilation
// of the source code or deferred for lazy compilation at a later point.
class V8_EXPORT_PRIVATE Compiler : public AllStatic {
class Compiler : public AllStatic {
public:
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
......
......@@ -255,17 +255,11 @@ HARMONY_STAGED(FLAG_STAGED_FEATURES)
HARMONY_SHIPPING(FLAG_SHIPPING_FEATURES)
#undef FLAG_SHIPPING_FEATURES
// Flags for future configurations.
DEFINE_BOOL(future, false,
"Implies all staged features that we want to ship in the "
"not-too-far future")
DEFINE_IMPLICATION(future, ignition_staging)
DEFINE_BOOL(ignition_staging, false, "use ignition with all staged features")
DEFINE_IMPLICATION(ignition_staging, ignition)
DEFINE_IMPLICATION(ignition_staging, compiler_dispatcher)
DEFINE_IMPLICATION(ignition_staging, validate_asm)
// Flags for experimental implementation features.
DEFINE_BOOL(allocation_site_pretenuring, true,
"pretenure with allocation sites")
......@@ -306,6 +300,9 @@ DEFINE_BOOL(string_slices, true, "use string slices")
// Flags for Ignition.
DEFINE_BOOL(ignition, false, "use ignition interpreter")
DEFINE_BOOL(ignition_staging, false, "use ignition with all staged features")
DEFINE_IMPLICATION(ignition_staging, ignition)
DEFINE_IMPLICATION(ignition_staging, compiler_dispatcher)
DEFINE_STRING(ignition_filter, "*", "filter for ignition interpreter")
DEFINE_BOOL(ignition_deadcode, true,
"use ignition dead code elimination optimizer")
......@@ -523,6 +520,7 @@ DEFINE_BOOL(wasm_loop_assignment_analysis, true,
"perform loop assignment analysis for WASM")
DEFINE_BOOL(validate_asm, true, "validate asm.js modules before compiling")
DEFINE_IMPLICATION(ignition_staging, validate_asm)
DEFINE_BOOL(suppress_asm_messages, false,
"don't emit asm.js related messages (for golden file testing)")
DEFINE_BOOL(trace_asm_time, false, "log asm.js timing info to the console")
......
......@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --ignition-filter=f
// This test tests that full code compiled without debug break slots
// is recompiled with debug break slots when debugging is started.
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --ignition-filter=f
var Debug = debug.Debug;
var break_count = 0;
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --ignition-filter=f
// Flags: --no-turbo
// TODO(yangguo): fix for turbofan
......@@ -15,6 +16,6 @@ function f(x) {
var stack_lines = f(2).split("\n");
assertTrue(/at f \(.*?:11:12\)/.test(stack_lines[1]));
assertTrue(/at f \(.*?:13:10\)/.test(stack_lines[2]));
assertTrue(/at f \(.*?:13:10\)/.test(stack_lines[3]));
assertTrue(/at f \(.*?:12:12\)/.test(stack_lines[1]));
assertTrue(/at f \(.*?:14:10\)/.test(stack_lines[2]));
assertTrue(/at f \(.*?:14:10\)/.test(stack_lines[3]));
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --ignition
// Flags: --ignition --ignition-filter=-foo
function* foo() { yield 42 }
function* goo() { yield 42 }
......
......@@ -112,9 +112,7 @@ TEST_F(CompilerDispatcherJobTest, StateTransitions) {
job->Parse();
ASSERT_TRUE(job->status() == CompileJobStatus::kParsed);
ASSERT_TRUE(job->FinalizeParsingOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyze);
ASSERT_TRUE(job->AnalyzeOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kAnalyzed);
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToAnalyse);
ASSERT_TRUE(job->PrepareToCompileOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile);
job->Compile();
......@@ -155,7 +153,6 @@ TEST_F(CompilerDispatcherJobTest, ScopeChain) {
job->PrepareToParseOnMainThread();
job->Parse();
ASSERT_TRUE(job->FinalizeParsingOnMainThread());
ASSERT_TRUE(job->AnalyzeOnMainThread());
ASSERT_TRUE(job->PrepareToCompileOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kReadyToCompile);
......@@ -192,7 +189,6 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
job->PrepareToParseOnMainThread();
job->Parse();
job->FinalizeParsingOnMainThread();
job->AnalyzeOnMainThread();
job->PrepareToCompileOnMainThread();
job->Compile();
ASSERT_TRUE(job->FinalizeCompilingOnMainThread());
......@@ -205,7 +201,7 @@ TEST_F(CompilerDispatcherJobTest, CompileAndRun) {
ASSERT_TRUE(job->status() == CompileJobStatus::kInitial);
}
TEST_F(CompilerDispatcherJobTest, CompileFailureToAnalyse) {
TEST_F(CompilerDispatcherJobTest, CompileFailureToPrepare) {
std::string raw_script("() { var a = ");
for (int i = 0; i < 100000; i++) {
raw_script += "'x' + ";
......@@ -219,7 +215,7 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToAnalyse) {
job->PrepareToParseOnMainThread();
job->Parse();
job->FinalizeParsingOnMainThread();
ASSERT_FALSE(job->AnalyzeOnMainThread());
ASSERT_FALSE(job->PrepareToCompileOnMainThread());
ASSERT_TRUE(job->status() == CompileJobStatus::kFailed);
ASSERT_TRUE(i_isolate()->has_pending_exception());
......@@ -242,7 +238,6 @@ TEST_F(CompilerDispatcherJobTest, CompileFailureToFinalize) {
job->PrepareToParseOnMainThread();
job->Parse();
job->FinalizeParsingOnMainThread();
job->AnalyzeOnMainThread();
job->PrepareToCompileOnMainThread();
job->Compile();
ASSERT_FALSE(job->FinalizeCompilingOnMainThread());
......@@ -287,7 +282,6 @@ TEST_F(CompilerDispatcherJobTest, CompileOnBackgroundThread) {
job->PrepareToParseOnMainThread();
job->Parse();
job->FinalizeParsingOnMainThread();
job->AnalyzeOnMainThread();
job->PrepareToCompileOnMainThread();
base::Semaphore semaphore(0);
......@@ -320,7 +314,6 @@ TEST_F(CompilerDispatcherJobTest, LazyInnerFunctions) {
job->PrepareToParseOnMainThread();
job->Parse();
ASSERT_TRUE(job->FinalizeParsingOnMainThread());
ASSERT_TRUE(job->AnalyzeOnMainThread());
ASSERT_TRUE(job->PrepareToCompileOnMainThread());
job->Compile();
ASSERT_TRUE(job->FinalizeCompilingOnMainThread());
......
......@@ -8,13 +8,10 @@
#include "src/base/platform/semaphore.h"
#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/handles.h"
#include "src/objects-inl.h"
#include "src/parsing/parse-info.h"
#include "src/v8.h"
#include "src/zone/zone.h"
#include "test/unittests/compiler-dispatcher/compiler-dispatcher-helper.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -805,97 +802,5 @@ TEST_F(CompilerDispatcherTest, EnqueueAndStep) {
platform.ClearBackgroundTasks();
}
TEST_F(CompilerDispatcherTest, EnqueueParsed) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] =
"function g() { var y = 1; function f17(x) { return x * y }; return f17; "
"} g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Zone zone(i_isolate()->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, shared);
ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(dispatcher.Enqueue(shared, parse_info.literal()));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() ==
CompileJobStatus::kAnalyzed);
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
ASSERT_FALSE(platform.BackgroundTasksPending());
}
TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script[] =
"function g() { var y = 1; function f18(x) { return x * y }; return f18; "
"} g();";
Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script));
Handle<SharedFunctionInfo> shared(f->shared(), i_isolate());
Zone zone(i_isolate()->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, shared);
ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(dispatcher.EnqueueAndStep(shared, parse_info.literal()));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() ==
CompileJobStatus::kReadyToCompile);
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_TRUE(platform.BackgroundTasksPending());
platform.ClearIdleTask();
platform.ClearBackgroundTasks();
}
TEST_F(CompilerDispatcherTest, FinishAllNow) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
const char script1[] =
"function g() { var y = 1; function f19(x) { return x + y }; return f19; "
"} g();";
Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1));
Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate());
const char script2[] =
"function g() { var y = 1; function f20(x) { return x * y }; return f20; "
"} g();";
Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2));
Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate());
ASSERT_FALSE(shared1->is_compiled());
ASSERT_FALSE(shared2->is_compiled());
// Enqueue shared1 as already parsed.
Zone zone(i_isolate()->allocator(), ZONE_NAME);
ParseInfo parse_info(&zone, shared1);
ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info));
ASSERT_TRUE(dispatcher.Enqueue(shared1, parse_info.literal()));
// Enqueue shared2 for parsing and compiling
ASSERT_TRUE(dispatcher.Enqueue(shared2));
ASSERT_TRUE(dispatcher.FinishAllNow());
// Finishing removes the SFI from the queue.
ASSERT_FALSE(dispatcher.IsEnqueued(shared1));
ASSERT_FALSE(dispatcher.IsEnqueued(shared2));
ASSERT_TRUE(shared1->is_compiled());
ASSERT_TRUE(shared2->is_compiled());
ASSERT_TRUE(platform.IdleTaskPending());
platform.ClearIdleTask();
}
} // namespace internal
} // namespace v8
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