Chromium Code Reviews| Index: runtime/vm/compiler.cc |
| diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
| index 6655af303bb89fda05a02c6a3a3da60a6eca7891..88101121c817528b43f5e0fe60f97d1044e3fac6 100644 |
| --- a/runtime/vm/compiler.cc |
| +++ b/runtime/vm/compiler.cc |
| @@ -1163,8 +1163,8 @@ RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
| "OptimizedFunction", function); |
| // Optimization must happen in non-mutator/Dart thread if background |
| - // compilation is on. |
| - ASSERT(!FLAG_background_compilation || |
| + // compilation is on. OSR compilation still occura in the main thread. |
| + ASSERT((osr_id != Thread::kNoDeoptId) || !FLAG_background_compilation || |
| !thread->isolate()->MutatorThreadIsCurrentThread()); |
| CompilationPipeline* pipeline = |
| CompilationPipeline::New(thread->zone(), function); |
| @@ -1420,6 +1420,7 @@ class CompilationWorkQueue : public ValueObject { |
| } |
| intptr_t IsEmpty() const { return data_.Length() == 0; } |
| + intptr_t Length() const { return data_.Length(); } |
| // Adds to the queue only if 'function' is not already in there. |
| void PushFront(const Function& function) { |
| @@ -1446,6 +1447,13 @@ class CompilationWorkQueue : public ValueObject { |
| return Function::Cast(result).raw(); |
| } |
| + RawFunction* Last() { |
| + ASSERT(!IsEmpty()); |
| + Object& result = Object::Handle(); |
| + result = data_.At(data_.Length() - 1); |
| + return Function::Cast(result).raw(); |
| + } |
| + |
| private: |
| GrowableObjectArray& data_; |
| @@ -1455,38 +1463,46 @@ class CompilationWorkQueue : public ValueObject { |
| BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
| : isolate_(isolate), running_(true), done_(new bool()), |
| - monitor_(new Monitor()), done_monitor_(new Monitor()) { |
| + queue_monitor_(new Monitor()), done_monitor_(new Monitor()), |
| + queue_length_(0) { |
| *done_ = false; |
| } |
| void BackgroundCompiler::Run() { |
| while (running_) { |
|
siva
2015/10/16 23:29:40
running_ is being accessed here without holding th
srdjan
2015/10/16 23:50:17
Yes, running_ is not guarded by queue lock. It can
|
| - { |
| - // Wait to be notified when the work queue is not empty. |
| - MonitorLocker ml(monitor_); |
| - ml.Wait(); |
| - } |
| - |
| + // Maybe something is already in the queue, check first before waiting |
| + // to be notified. |
| Thread::EnterIsolateAsHelper(isolate_); |
| { |
| Thread* thread = Thread::Current(); |
| StackZone stack_zone(thread); |
| HANDLESCOPE(thread); |
| - Function& function = Function::Handle(); |
| - function = RemoveOrNull(); |
| - while (!function.IsNull()) { |
| - const Error& error = Error::Handle( |
| + Zone* zone = stack_zone.GetZone(); |
| + Function& function = Function::Handle(zone); |
| + Function& temp_function = Function::Handle(zone); |
| + function = LastOrNull(); |
| + while (!function.IsNull() && running_) { |
|
siva
2015/10/16 23:29:40
Ditto question about running_ accessed here withou
srdjan
2015/10/16 23:50:17
ditto.
|
| + const Error& error = Error::Handle(zone, |
| Compiler::CompileOptimizedFunction(thread, function)); |
| // TODO(srdjan): We do not expect errors while compiling optimized |
| // code, any errors should have been caught when compiling |
| // unoptimized code. |
| // If it still happens mark function as not optimizable. |
| ASSERT(error.IsNull()); |
| - function = RemoveOrNull(); |
| + temp_function = RemoveOrNull(); |
| + ASSERT(temp_function.raw() == function.raw()); |
| + function = LastOrNull(); |
| } |
| } |
| Thread::ExitIsolateAsHelper(); |
| + { |
| + // Wait to be notified when the work queue is not empty. |
| + MonitorLocker ml(queue_monitor_); |
| + while (queue_length() == 0) { |
|
siva
2015/10/16 23:29:40
while ((queue_length() == 0) && running_) {
}
srdjan
2015/10/16 23:50:17
Done.
|
| + ml.Wait(); |
| + } |
| + } |
| } |
| { |
| // Notify that the thread is done. |
| @@ -1502,18 +1518,28 @@ void BackgroundCompiler::CompileOptimized(const Function& function) { |
| } |
| -void BackgroundCompiler::Add(const Function& f) const { |
| - MonitorLocker ml(monitor_); |
| +void BackgroundCompiler::Add(const Function& f) { |
| + MonitorLocker ml(queue_monitor_); |
| CompilationWorkQueue queue(isolate_); |
| queue.PushFront(f); |
| + set_queue_length(queue.Length()); |
| ml.Notify(); |
| } |
| -RawFunction* BackgroundCompiler::RemoveOrNull() const { |
| - MonitorLocker ml(monitor_); |
| +RawFunction* BackgroundCompiler::RemoveOrNull() { |
| + MonitorLocker ml(queue_monitor_); |
| + CompilationWorkQueue queue(isolate_); |
| + if (queue.IsEmpty()) return Function::null(); |
| + set_queue_length(queue.Length() - 1); |
| + return queue.PopBack(); |
| +} |
| + |
| + |
| +RawFunction* BackgroundCompiler::LastOrNull() const { |
| + MonitorLocker ml(queue_monitor_); |
| CompilationWorkQueue queue(isolate_); |
| - return queue.IsEmpty() ? Function::null() : queue.PopBack(); |
| + return queue.IsEmpty() ? Function::null() : queue.Last(); |
| } |
| @@ -1521,16 +1547,16 @@ void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
| if (task == NULL) { |
| return; |
| } |
| - Monitor* monitor = task->monitor_; |
| + Monitor* monitor = task->queue_monitor_; |
| Monitor* done_monitor = task->done_monitor_; |
| bool* task_done = task->done_; |
| // Wake up compiler task and stop it. |
| { |
| - MonitorLocker ml(task->monitor_); |
| + MonitorLocker ml(task->queue_monitor_); |
| task->running_ = false; |
| // 'task' will be deleted by thread pool. |
| task = NULL; |
| - ml.Notify(); |
| + ml.Notify(); // Stop waiting for the queue. |
| } |
| { |