Index: runtime/vm/compiler.cc |
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
index 6655af303bb89fda05a02c6a3a3da60a6eca7891..51ae1464a7ac688f3dc197d6c86abfd854849eb1 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. |
siva
2015/10/16 23:29:40
still occurs
srdjan
2015/10/16 23:50:17
Done.
|
+ ASSERT((osr_id != Thread::kNoDeoptId) || !FLAG_background_compilation || |
!thread->isolate()->MutatorThreadIsCurrentThread()); |
CompilationPipeline* pipeline = |
CompilationPipeline::New(thread->zone(), function); |
@@ -1446,6 +1446,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(); |
siva
2015/10/16 23:29:40
maybe just:
return RawFunction::RawCast(data_.At(
srdjan
2015/10/16 23:50:17
Done: Function::RawCast.
|
+ } |
+ |
private: |
GrowableObjectArray& data_; |
@@ -1455,38 +1462,48 @@ 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()) { |
*done_ = false; |
} |
void BackgroundCompiler::Run() { |
while (running_) { |
- { |
- // 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_) { |
+ 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_); |
+ // TODO(srdjan): Add a loop here, while queue is empty. Figure out how. |
+ // Currently we may block while there is still something in the queue. |
+ // We cannot access the queue as we cannot create handles here. |
+ // We cannot call EnterIsolateAsHelper to allocate handles because |
+ // safepoint would not be reachable here otherwise. |
+ ml.Wait(); |
+ } |
} |
{ |
// Notify that the thread is done. |
@@ -1503,7 +1520,7 @@ void BackgroundCompiler::CompileOptimized(const Function& function) { |
void BackgroundCompiler::Add(const Function& f) const { |
- MonitorLocker ml(monitor_); |
+ MonitorLocker ml(queue_monitor_); |
CompilationWorkQueue queue(isolate_); |
queue.PushFront(f); |
ml.Notify(); |
@@ -1511,26 +1528,33 @@ void BackgroundCompiler::Add(const Function& f) const { |
RawFunction* BackgroundCompiler::RemoveOrNull() const { |
- MonitorLocker ml(monitor_); |
+ MonitorLocker ml(queue_monitor_); |
CompilationWorkQueue queue(isolate_); |
return queue.IsEmpty() ? Function::null() : queue.PopBack(); |
} |
+RawFunction* BackgroundCompiler::LastOrNull() const { |
+ MonitorLocker ml(queue_monitor_); |
+ CompilationWorkQueue queue(isolate_); |
+ return queue.IsEmpty() ? Function::null() : queue.Last(); |
+} |
+ |
+ |
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. |
} |
{ |