Index: src/compiler.cc |
diff --git a/src/compiler.cc b/src/compiler.cc |
index 9a5afe99dae54bb6a9afc2373bad51b165161acc..1eab32538f53c12431df61b3298d7a72c912cfb9 100644 |
--- a/src/compiler.cc |
+++ b/src/compiler.cc |
@@ -260,10 +260,18 @@ CompilationJob::Status CompilationJob::PrepareJob() { |
} |
CompilationJob::Status CompilationJob::ExecuteJob() { |
- DisallowHeapAllocation no_allocation; |
- DisallowHandleAllocation no_handles; |
- DisallowHandleDereference no_deref; |
- DisallowCodeDependencyChange no_dependency_change; |
+ std::unique_ptr<DisallowHeapAllocation> no_allocation; |
+ std::unique_ptr<DisallowHandleAllocation> no_handles; |
+ std::unique_ptr<DisallowHandleDereference> no_deref; |
+ std::unique_ptr<DisallowCodeDependencyChange> no_dependency_change; |
+ if (can_execute_on_background_thread()) { |
+ no_allocation.reset(new DisallowHeapAllocation()); |
+ no_handles.reset(new DisallowHandleAllocation()); |
+ no_deref.reset(new DisallowHandleDereference()); |
+ no_dependency_change.reset(new DisallowCodeDependencyChange()); |
+ } else { |
+ DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); |
+ } |
// Delegate to the underlying implementation. |
DCHECK(state() == State::kReadyToExecute); |
@@ -283,6 +291,57 @@ CompilationJob::Status CompilationJob::FinalizeJob() { |
return UpdateState(FinalizeJobImpl(), State::kSucceeded); |
} |
+void CompilationJob::RecordUnoptimizedCompilationStats() const { |
+ int code_size; |
+ if (info()->has_bytecode_array()) { |
+ code_size = info()->bytecode_array()->SizeIncludingMetadata(); |
+ } else { |
+ code_size = info()->code()->SizeIncludingMetadata(); |
+ } |
+ |
+ Counters* counters = isolate()->counters(); |
+ // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. |
+ counters->total_baseline_code_size()->Increment(code_size); |
+ counters->total_baseline_compile_count()->Increment(1); |
+ |
+ // TODO(5203): Add timers for each phase of compilation. |
+} |
+ |
+void CompilationJob::RecordOptimizedCompilationStats() const { |
+ DCHECK(info()->IsOptimizing()); |
+ Handle<JSFunction> function = info()->closure(); |
+ if (!function->IsOptimized()) { |
+ // Concurrent recompilation and OSR may race. Increment only once. |
+ int opt_count = function->shared()->opt_count(); |
+ function->shared()->set_opt_count(opt_count + 1); |
+ } |
+ double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); |
+ double ms_optimize = time_taken_to_execute_.InMillisecondsF(); |
+ double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); |
+ if (FLAG_trace_opt) { |
+ PrintF("[optimizing "); |
+ function->ShortPrint(); |
+ PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, |
+ ms_codegen); |
+ } |
+ if (FLAG_trace_opt_stats) { |
+ static double compilation_time = 0.0; |
+ static int compiled_functions = 0; |
+ static int code_size = 0; |
+ |
+ compilation_time += (ms_creategraph + ms_optimize + ms_codegen); |
+ compiled_functions++; |
+ code_size += function->shared()->SourceSize(); |
+ PrintF("Compiled: %d functions with %d byte source size in %fms.\n", |
+ compiled_functions, code_size, compilation_time); |
+ } |
+ if (FLAG_hydrogen_stats) { |
+ isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, |
+ time_taken_to_execute_, |
+ time_taken_to_finalize_); |
+ } |
+} |
+ |
namespace { |
void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, |
@@ -341,41 +400,6 @@ void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { |
code->set_can_have_weak_objects(true); |
} |
-void CompilationJob::RecordOptimizationStats() { |
- DCHECK(info()->IsOptimizing()); |
- Handle<JSFunction> function = info()->closure(); |
- if (!function->IsOptimized()) { |
- // Concurrent recompilation and OSR may race. Increment only once. |
- int opt_count = function->shared()->opt_count(); |
- function->shared()->set_opt_count(opt_count + 1); |
- } |
- double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); |
- double ms_optimize = time_taken_to_execute_.InMillisecondsF(); |
- double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); |
- if (FLAG_trace_opt) { |
- PrintF("[optimizing "); |
- function->ShortPrint(); |
- PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, |
- ms_codegen); |
- } |
- if (FLAG_trace_opt_stats) { |
- static double compilation_time = 0.0; |
- static int compiled_functions = 0; |
- static int code_size = 0; |
- |
- compilation_time += (ms_creategraph + ms_optimize + ms_codegen); |
- compiled_functions++; |
- code_size += function->shared()->SourceSize(); |
- PrintF("Compiled: %d functions with %d byte source size in %fms.\n", |
- compiled_functions, code_size, compilation_time); |
- } |
- if (FLAG_hydrogen_stats) { |
- isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, |
- time_taken_to_execute_, |
- time_taken_to_finalize_); |
- } |
-} |
- |
// ---------------------------------------------------------------------------- |
// Local helper methods that make up the compilation pipeline. |
@@ -466,18 +490,24 @@ bool ShouldUseIgnition(CompilationInfo* info) { |
return info->shared_info()->PassesFilter(FLAG_ignition_filter); |
} |
-int CodeAndMetadataSize(CompilationInfo* info) { |
- if (info->has_bytecode_array()) { |
- return info->bytecode_array()->SizeIncludingMetadata(); |
+CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
+ // Function should have been parsed and analyzed before creating a compilation |
+ // job. |
+ DCHECK_NOT_NULL(info->literal()); |
+ DCHECK_NOT_NULL(info->scope()); |
+ |
+ EnsureFeedbackMetadata(info); |
+ if (ShouldUseIgnition(info)) { |
+ return interpreter::Interpreter::NewCompilationJob(info); |
+ } else { |
+ return FullCodeGenerator::NewCompilationJob(info); |
} |
- return info->code()->SizeIncludingMetadata(); |
} |
bool GenerateUnoptimizedCode(CompilationInfo* info) { |
- bool success; |
- EnsureFeedbackMetadata(info); |
if (FLAG_validate_asm && info->scope()->asm_module() && |
!info->shared_info()->is_asm_wasm_broken()) { |
+ EnsureFeedbackMetadata(info); |
MaybeHandle<FixedArray> wasm_data; |
wasm_data = AsmJs::ConvertAsmToWasm(info->parse_info()); |
if (!wasm_data.is_null()) { |
@@ -486,19 +516,13 @@ bool GenerateUnoptimizedCode(CompilationInfo* info) { |
return true; |
} |
} |
- if (ShouldUseIgnition(info)) { |
- success = interpreter::Interpreter::MakeBytecode(info); |
- } else { |
- success = FullCodeGenerator::MakeCode(info); |
- } |
- if (success) { |
- Isolate* isolate = info->isolate(); |
- Counters* counters = isolate->counters(); |
- // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually. |
- counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); |
- counters->total_baseline_compile_count()->Increment(1); |
- } |
- return success; |
+ |
+ std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
+ if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; |
+ if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; |
+ if (job->FinalizeJob() != CompilationJob::SUCCEEDED) return false; |
+ job->RecordUnoptimizedCompilationStats(); |
+ return true; |
} |
bool CompileUnoptimizedCode(CompilationInfo* info) { |
@@ -534,6 +558,19 @@ void InstallSharedCompilationResult(CompilationInfo* info, |
} |
} |
+void InstallUnoptimizedCode(CompilationInfo* info) { |
+ Handle<SharedFunctionInfo> shared = info->shared_info(); |
+ |
+ // Update the shared function info with the scope info. |
+ InstallSharedScopeInfo(info, shared); |
+ |
+ // Install compilation result on the shared function info |
+ InstallSharedCompilationResult(info, shared); |
+ |
+ // Record the function compilation event. |
+ RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
+} |
+ |
MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { |
VMState<COMPILER> state(info->isolate()); |
PostponeInterruptsScope postpone(info->isolate()); |
@@ -545,24 +582,27 @@ MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(CompilationInfo* info) { |
// Parse and update CompilationInfo with the results. |
if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
- Handle<SharedFunctionInfo> shared = info->shared_info(); |
- DCHECK_EQ(shared->language_mode(), info->literal()->language_mode()); |
+ DCHECK_EQ(info->shared_info()->language_mode(), |
+ info->literal()->language_mode()); |
// Compile either unoptimized code or bytecode for the interpreter. |
if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); |
- // Update the shared function info with the scope info. |
- InstallSharedScopeInfo(info, shared); |
- |
- // Install compilation result on the shared function info |
- InstallSharedCompilationResult(info, shared); |
- |
- // Record the function compilation event. |
- RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
+ InstallUnoptimizedCode(info); |
return info->code(); |
} |
+CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { |
+ CompilationJob::Status status = job->FinalizeJob(); |
+ if (status == CompilationJob::SUCCEEDED) { |
+ DCHECK(!job->info()->shared_info()->is_compiled()); |
+ InstallUnoptimizedCode(job->info()); |
+ job->RecordUnoptimizedCompilationStats(); |
+ } |
+ return status; |
+} |
+ |
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( |
Handle<JSFunction> function, BailoutId osr_ast_id) { |
Handle<SharedFunctionInfo> shared(function->shared()); |
@@ -684,7 +724,7 @@ bool GetOptimizedCodeNow(CompilationJob* job) { |
} |
// Success! |
- job->RecordOptimizationStats(); |
+ job->RecordOptimizedCompilationStats(); |
DCHECK(!isolate->has_pending_exception()); |
InsertCodeIntoOptimizedCodeMap(info); |
RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
@@ -844,6 +884,60 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function, |
return MaybeHandle<Code>(); |
} |
+CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) { |
+ CompilationInfo* info = job->info(); |
+ Isolate* isolate = info->isolate(); |
+ |
+ TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
+ RuntimeCallTimerScope runtimeTimer(isolate, |
+ &RuntimeCallStats::RecompileSynchronous); |
+ TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
+ isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
+ |
+ Handle<SharedFunctionInfo> shared = info->shared_info(); |
+ shared->code()->set_profiler_ticks(0); |
+ |
+ DCHECK(!shared->HasDebugInfo()); |
+ |
+ // 1) Optimization on the concurrent thread may have failed. |
+ // 2) The function may have already been optimized by OSR. Simply continue. |
+ // Except when OSR already disabled optimization for some reason. |
+ // 3) The code may have already been invalidated due to dependency change. |
+ // 4) Code generation may have failed. |
+ if (job->state() == CompilationJob::State::kReadyToFinalize) { |
+ if (shared->optimization_disabled()) { |
+ job->RetryOptimization(kOptimizationDisabled); |
+ } else if (info->dependencies()->HasAborted()) { |
+ job->RetryOptimization(kBailedOutDueToDependencyChange); |
+ } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { |
+ job->RecordOptimizedCompilationStats(); |
+ RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
+ if (shared |
+ ->SearchOptimizedCodeMap(info->context()->native_context(), |
+ info->osr_ast_id()) |
+ .code == nullptr) { |
+ InsertCodeIntoOptimizedCodeMap(info); |
+ } |
+ if (FLAG_trace_opt) { |
+ PrintF("[completed optimizing "); |
+ info->closure()->ShortPrint(); |
+ PrintF("]\n"); |
+ } |
+ info->closure()->ReplaceCode(*info->code()); |
+ return CompilationJob::SUCCEEDED; |
+ } |
+ } |
+ |
+ DCHECK(job->state() == CompilationJob::State::kFailed); |
+ if (FLAG_trace_opt) { |
+ PrintF("[aborted optimizing "); |
+ info->closure()->ShortPrint(); |
+ PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
+ } |
+ info->closure()->ReplaceCode(shared->code()); |
+ return CompilationJob::FAILED; |
+} |
+ |
class InterpreterActivationsFinder : public ThreadVisitor, |
public OptimizedFunctionVisitor { |
public: |
@@ -1895,58 +1989,28 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); |
} |
-void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { |
+CompilationJob* Compiler::PrepareUnoptimizedCompilationJob( |
+ CompilationInfo* info) { |
+ VMState<COMPILER> state(info->isolate()); |
+ std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
+ if (job->PrepareJob() != CompilationJob::SUCCEEDED) { |
+ return nullptr; |
+ } |
+ return job.release(); |
+} |
+ |
+bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { |
// Take ownership of compilation job. Deleting job also tears down the zone. |
std::unique_ptr<CompilationJob> job(raw_job); |
- CompilationInfo* info = job->info(); |
- Isolate* isolate = info->isolate(); |
- VMState<COMPILER> state(isolate); |
- TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
- RuntimeCallTimerScope runtimeTimer(isolate, |
- &RuntimeCallStats::RecompileSynchronous); |
- TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( |
- isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); |
- |
- Handle<SharedFunctionInfo> shared = info->shared_info(); |
- shared->code()->set_profiler_ticks(0); |
- |
- DCHECK(!shared->HasDebugInfo()); |
- |
- // 1) Optimization on the concurrent thread may have failed. |
- // 2) The function may have already been optimized by OSR. Simply continue. |
- // Except when OSR already disabled optimization for some reason. |
- // 3) The code may have already been invalidated due to dependency change. |
- // 4) Code generation may have failed. |
- if (job->state() == CompilationJob::State::kReadyToFinalize) { |
- if (shared->optimization_disabled()) { |
- job->RetryOptimization(kOptimizationDisabled); |
- } else if (info->dependencies()->HasAborted()) { |
- job->RetryOptimization(kBailedOutDueToDependencyChange); |
- } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { |
- job->RecordOptimizationStats(); |
- RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); |
- if (shared->SearchOptimizedCodeMap(info->context()->native_context(), |
- info->osr_ast_id()).code == nullptr) { |
- InsertCodeIntoOptimizedCodeMap(info); |
- } |
- if (FLAG_trace_opt) { |
- PrintF("[completed optimizing "); |
- info->closure()->ShortPrint(); |
- PrintF("]\n"); |
- } |
- info->closure()->ReplaceCode(*info->code()); |
- return; |
- } |
- } |
- |
- DCHECK(job->state() == CompilationJob::State::kFailed); |
- if (FLAG_trace_opt) { |
- PrintF("[aborted optimizing "); |
- info->closure()->ShortPrint(); |
- PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
+ VMState<COMPILER> state(job->info()->isolate()); |
+ if (job->info()->IsOptimizing()) { |
+ return FinalizeOptimizedCompilationJob(job.get()) == |
+ CompilationJob::SUCCEEDED; |
+ } else { |
+ return FinalizeUnoptimizedCompilationJob(job.get()) == |
+ CompilationJob::SUCCEEDED; |
} |
- info->closure()->ReplaceCode(shared->code()); |
} |
void Compiler::PostInstantiation(Handle<JSFunction> function, |