5 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" 7 #include "src/base/atomicops.h" 8 #include "src/base/template-utils.h" 9 #include "src/cancelable-task.h" 10 #include "src/compiler.h" 11 #include "src/counters.h" 12 #include "src/isolate.h" 13 #include "src/objects-inl.h" 14 #include "src/optimized-compilation-info.h" 15 #include "src/tracing/trace-event.h" 23 void DisposeCompilationJob(OptimizedCompilationJob* job,
24 bool restore_function_code) {
25 if (restore_function_code) {
26 Handle<JSFunction>
function = job->compilation_info()->closure();
27 function->set_code(function->shared()->GetCode());
28 if (function->IsInOptimizationQueue()) {
29 function->ClearOptimizationMarker();
47 worker_thread_runtime_call_stats_(
48 isolate->counters()->worker_thread_runtime_call_stats()),
49 dispatcher_(dispatcher) {
50 base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
51 ++dispatcher_->ref_count_;
58 void RunInternal()
override {
65 worker_thread_runtime_call_stats_);
67 runtime_call_stats_scope.Get(),
68 RuntimeCallCounterId::kRecompileConcurrent);
71 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT(
"v8.compile"),
72 "V8.RecompileConcurrent");
74 if (dispatcher_->recompilation_delay_ != 0) {
75 base::OS::Sleep(base::TimeDelta::FromMilliseconds(
76 dispatcher_->recompilation_delay_));
79 dispatcher_->CompileNext(dispatcher_->NextInput(
true));
82 base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
83 if (--dispatcher_->ref_count_ == 0) {
84 dispatcher_->ref_count_zero_.NotifyOne();
96 OptimizingCompileDispatcher::~OptimizingCompileDispatcher() {
99 base::MutexGuard lock_guard(&ref_count_mutex_);
100 DCHECK_EQ(0, ref_count_);
103 DCHECK_EQ(0, input_queue_length_);
104 DeleteArray(input_queue_);
107 OptimizedCompilationJob* OptimizingCompileDispatcher::NextInput(
108 bool check_if_flushing) {
109 base::MutexGuard access_input_queue_(&input_queue_mutex_);
110 if (input_queue_length_ == 0)
return nullptr;
111 OptimizedCompilationJob* job = input_queue_[InputQueueIndex(0)];
112 DCHECK_NOT_NULL(job);
113 input_queue_shift_ = InputQueueIndex(1);
114 input_queue_length_--;
115 if (check_if_flushing) {
116 if (mode_ == FLUSH) {
117 AllowHandleDereference allow_handle_dereference;
118 DisposeCompilationJob(job,
true);
125 void OptimizingCompileDispatcher::CompileNext(OptimizedCompilationJob* job) {
129 CompilationJob::Status status = job->ExecuteJob();
135 base::MutexGuard access_output_queue_(&output_queue_mutex_);
136 output_queue_.push(job);
137 isolate_->stack_guard()->RequestInstallCode();
140 void OptimizingCompileDispatcher::FlushOutputQueue(
bool restore_function_code) {
142 OptimizedCompilationJob* job =
nullptr;
144 base::MutexGuard access_output_queue_(&output_queue_mutex_);
145 if (output_queue_.empty())
return;
146 job = output_queue_.front();
150 DisposeCompilationJob(job, restore_function_code);
154 void OptimizingCompileDispatcher::Flush(BlockingBehavior blocking_behavior) {
155 if (blocking_behavior == BlockingBehavior::kDontBlock) {
156 if (FLAG_block_concurrent_recompilation) Unblock();
157 base::MutexGuard access_input_queue_(&input_queue_mutex_);
158 while (input_queue_length_ > 0) {
159 OptimizedCompilationJob* job = input_queue_[InputQueueIndex(0)];
160 DCHECK_NOT_NULL(job);
161 input_queue_shift_ = InputQueueIndex(1);
162 input_queue_length_--;
163 DisposeCompilationJob(job,
true);
165 FlushOutputQueue(
true);
166 if (FLAG_trace_concurrent_recompilation) {
167 PrintF(
" ** Flushed concurrent recompilation queues (not blocking).\n");
172 if (FLAG_block_concurrent_recompilation) Unblock();
174 base::MutexGuard lock_guard(&ref_count_mutex_);
175 while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
178 FlushOutputQueue(
true);
179 if (FLAG_trace_concurrent_recompilation) {
180 PrintF(
" ** Flushed concurrent recompilation queues.\n");
184 void OptimizingCompileDispatcher::Stop() {
186 if (FLAG_block_concurrent_recompilation) Unblock();
188 base::MutexGuard lock_guard(&ref_count_mutex_);
189 while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
193 if (recompilation_delay_ != 0) {
196 while (input_queue_length_ > 0) CompileNext(NextInput());
197 InstallOptimizedFunctions();
199 FlushOutputQueue(
false);
203 void OptimizingCompileDispatcher::InstallOptimizedFunctions() {
204 HandleScope handle_scope(isolate_);
207 OptimizedCompilationJob* job =
nullptr;
209 base::MutexGuard access_output_queue_(&output_queue_mutex_);
210 if (output_queue_.empty())
return;
211 job = output_queue_.front();
214 OptimizedCompilationInfo* info = job->compilation_info();
215 Handle<JSFunction>
function(*info->closure(), isolate_);
216 if (function->HasOptimizedCode()) {
217 if (FLAG_trace_concurrent_recompilation) {
218 PrintF(
" ** Aborting compilation for ");
219 function->ShortPrint();
220 PrintF(
" as it has already been optimized.\n");
222 DisposeCompilationJob(job,
false);
224 Compiler::FinalizeOptimizedCompilationJob(job, isolate_);
229 void OptimizingCompileDispatcher::QueueForOptimization(
230 OptimizedCompilationJob* job) {
231 DCHECK(IsQueueAvailable());
234 base::MutexGuard access_input_queue(&input_queue_mutex_);
235 DCHECK_LT(input_queue_length_, input_queue_capacity_);
236 input_queue_[InputQueueIndex(input_queue_length_)] = job;
237 input_queue_length_++;
239 if (FLAG_block_concurrent_recompilation) {
242 V8::GetCurrentPlatform()->CallOnWorkerThread(
243 base::make_unique<CompileTask>(isolate_,
this));
247 void OptimizingCompileDispatcher::Unblock() {
248 while (blocked_jobs_ > 0) {
249 V8::GetCurrentPlatform()->CallOnWorkerThread(
250 base::make_unique<CompileTask>(isolate_,
this));