| 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,
|
|
|