Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 | 8 |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
| (...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 | 1156 |
| 1157 | 1157 |
| 1158 RawError* Compiler::CompileOptimizedFunction(Thread* thread, | 1158 RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
| 1159 const Function& function, | 1159 const Function& function, |
| 1160 intptr_t osr_id) { | 1160 intptr_t osr_id) { |
| 1161 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); | 1161 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); |
| 1162 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, | 1162 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, |
| 1163 "OptimizedFunction", function); | 1163 "OptimizedFunction", function); |
| 1164 | 1164 |
| 1165 // Optimization must happen in non-mutator/Dart thread if background | 1165 // Optimization must happen in non-mutator/Dart thread if background |
| 1166 // compilation is on. | 1166 // compilation is on. OSR compilation still occura in the main thread. |
| 1167 ASSERT(!FLAG_background_compilation || | 1167 ASSERT((osr_id != Thread::kNoDeoptId) || !FLAG_background_compilation || |
| 1168 !thread->isolate()->MutatorThreadIsCurrentThread()); | 1168 !thread->isolate()->MutatorThreadIsCurrentThread()); |
| 1169 CompilationPipeline* pipeline = | 1169 CompilationPipeline* pipeline = |
| 1170 CompilationPipeline::New(thread->zone(), function); | 1170 CompilationPipeline::New(thread->zone(), function); |
| 1171 return CompileFunctionHelper(pipeline, function, true, osr_id); | 1171 return CompileFunctionHelper(pipeline, function, true, osr_id); |
| 1172 } | 1172 } |
| 1173 | 1173 |
| 1174 | 1174 |
| 1175 // This is only used from unit tests. | 1175 // This is only used from unit tests. |
| 1176 RawError* Compiler::CompileParsedFunction( | 1176 RawError* Compiler::CompileParsedFunction( |
| 1177 ParsedFunction* parsed_function) { | 1177 ParsedFunction* parsed_function) { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1413 // PushFront and PopBack to add and read from queue. | 1413 // PushFront and PopBack to add and read from queue. |
| 1414 // TODO(srdjan): Write a more efficient implementation. | 1414 // TODO(srdjan): Write a more efficient implementation. |
| 1415 class CompilationWorkQueue : public ValueObject { | 1415 class CompilationWorkQueue : public ValueObject { |
| 1416 public: | 1416 public: |
| 1417 explicit CompilationWorkQueue(Isolate* isolate) : | 1417 explicit CompilationWorkQueue(Isolate* isolate) : |
| 1418 data_(GrowableObjectArray::Handle()) { | 1418 data_(GrowableObjectArray::Handle()) { |
| 1419 data_ = isolate->background_compilation_queue(); | 1419 data_ = isolate->background_compilation_queue(); |
| 1420 } | 1420 } |
| 1421 | 1421 |
| 1422 intptr_t IsEmpty() const { return data_.Length() == 0; } | 1422 intptr_t IsEmpty() const { return data_.Length() == 0; } |
| 1423 intptr_t Length() const { return data_.Length(); } | |
| 1423 | 1424 |
| 1424 // Adds to the queue only if 'function' is not already in there. | 1425 // Adds to the queue only if 'function' is not already in there. |
| 1425 void PushFront(const Function& function) { | 1426 void PushFront(const Function& function) { |
| 1426 for (intptr_t i = 0; i < data_.Length(); i++) { | 1427 for (intptr_t i = 0; i < data_.Length(); i++) { |
| 1427 if (data_.At(i) == function.raw()) { | 1428 if (data_.At(i) == function.raw()) { |
| 1428 return; | 1429 return; |
| 1429 } | 1430 } |
| 1430 } | 1431 } |
| 1431 // Insert new element in front. | 1432 // Insert new element in front. |
| 1432 Object& f = Object::Handle(); | 1433 Object& f = Object::Handle(); |
| 1433 data_.Add(f); | 1434 data_.Add(f); |
| 1434 for (intptr_t i = data_.Length() - 1; i > 0; i--) { | 1435 for (intptr_t i = data_.Length() - 1; i > 0; i--) { |
| 1435 f = data_.At(i - 1); | 1436 f = data_.At(i - 1); |
| 1436 data_.SetAt(i, f); | 1437 data_.SetAt(i, f); |
| 1437 } | 1438 } |
| 1438 data_.SetAt(0, function); | 1439 data_.SetAt(0, function); |
| 1439 } | 1440 } |
| 1440 | 1441 |
| 1441 RawFunction* PopBack() { | 1442 RawFunction* PopBack() { |
| 1442 ASSERT(!IsEmpty()); | 1443 ASSERT(!IsEmpty()); |
| 1443 Object& result = Object::Handle(); | 1444 Object& result = Object::Handle(); |
| 1444 result = data_.At(data_.Length() - 1); | 1445 result = data_.At(data_.Length() - 1); |
| 1445 data_.SetLength(data_.Length() - 1); | 1446 data_.SetLength(data_.Length() - 1); |
| 1446 return Function::Cast(result).raw(); | 1447 return Function::Cast(result).raw(); |
| 1447 } | 1448 } |
| 1448 | 1449 |
| 1450 RawFunction* Last() { | |
| 1451 ASSERT(!IsEmpty()); | |
| 1452 Object& result = Object::Handle(); | |
| 1453 result = data_.At(data_.Length() - 1); | |
| 1454 return Function::Cast(result).raw(); | |
| 1455 } | |
| 1456 | |
| 1449 private: | 1457 private: |
| 1450 GrowableObjectArray& data_; | 1458 GrowableObjectArray& data_; |
| 1451 | 1459 |
| 1452 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); | 1460 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); |
| 1453 }; | 1461 }; |
| 1454 | 1462 |
| 1455 | 1463 |
| 1456 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) | 1464 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
| 1457 : isolate_(isolate), running_(true), done_(new bool()), | 1465 : isolate_(isolate), running_(true), done_(new bool()), |
| 1458 monitor_(new Monitor()), done_monitor_(new Monitor()) { | 1466 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), |
| 1467 queue_length_(0) { | |
| 1459 *done_ = false; | 1468 *done_ = false; |
| 1460 } | 1469 } |
| 1461 | 1470 |
| 1462 | 1471 |
| 1463 void BackgroundCompiler::Run() { | 1472 void BackgroundCompiler::Run() { |
| 1464 while (running_) { | 1473 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
| |
| 1465 { | 1474 // Maybe something is already in the queue, check first before waiting |
| 1466 // Wait to be notified when the work queue is not empty. | 1475 // to be notified. |
| 1467 MonitorLocker ml(monitor_); | |
| 1468 ml.Wait(); | |
| 1469 } | |
| 1470 | |
| 1471 Thread::EnterIsolateAsHelper(isolate_); | 1476 Thread::EnterIsolateAsHelper(isolate_); |
| 1472 { | 1477 { |
| 1473 Thread* thread = Thread::Current(); | 1478 Thread* thread = Thread::Current(); |
| 1474 StackZone stack_zone(thread); | 1479 StackZone stack_zone(thread); |
| 1475 HANDLESCOPE(thread); | 1480 HANDLESCOPE(thread); |
| 1476 Function& function = Function::Handle(); | 1481 Zone* zone = stack_zone.GetZone(); |
| 1477 function = RemoveOrNull(); | 1482 Function& function = Function::Handle(zone); |
| 1478 while (!function.IsNull()) { | 1483 Function& temp_function = Function::Handle(zone); |
| 1479 const Error& error = Error::Handle( | 1484 function = LastOrNull(); |
| 1485 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.
| |
| 1486 const Error& error = Error::Handle(zone, | |
| 1480 Compiler::CompileOptimizedFunction(thread, function)); | 1487 Compiler::CompileOptimizedFunction(thread, function)); |
| 1481 // TODO(srdjan): We do not expect errors while compiling optimized | 1488 // TODO(srdjan): We do not expect errors while compiling optimized |
| 1482 // code, any errors should have been caught when compiling | 1489 // code, any errors should have been caught when compiling |
| 1483 // unoptimized code. | 1490 // unoptimized code. |
| 1484 // If it still happens mark function as not optimizable. | 1491 // If it still happens mark function as not optimizable. |
| 1485 ASSERT(error.IsNull()); | 1492 ASSERT(error.IsNull()); |
| 1486 function = RemoveOrNull(); | 1493 temp_function = RemoveOrNull(); |
| 1494 ASSERT(temp_function.raw() == function.raw()); | |
| 1495 function = LastOrNull(); | |
| 1487 } | 1496 } |
| 1488 } | 1497 } |
| 1489 Thread::ExitIsolateAsHelper(); | 1498 Thread::ExitIsolateAsHelper(); |
| 1499 { | |
| 1500 // Wait to be notified when the work queue is not empty. | |
| 1501 MonitorLocker ml(queue_monitor_); | |
| 1502 while (queue_length() == 0) { | |
|
siva
2015/10/16 23:29:40
while ((queue_length() == 0) && running_) {
}
srdjan
2015/10/16 23:50:17
Done.
| |
| 1503 ml.Wait(); | |
| 1504 } | |
| 1505 } | |
| 1490 } | 1506 } |
| 1491 { | 1507 { |
| 1492 // Notify that the thread is done. | 1508 // Notify that the thread is done. |
| 1493 MonitorLocker ml_done(done_monitor_); | 1509 MonitorLocker ml_done(done_monitor_); |
| 1494 *done_ = true; | 1510 *done_ = true; |
| 1495 ml_done.Notify(); | 1511 ml_done.Notify(); |
| 1496 } | 1512 } |
| 1497 } | 1513 } |
| 1498 | 1514 |
| 1499 | 1515 |
| 1500 void BackgroundCompiler::CompileOptimized(const Function& function) { | 1516 void BackgroundCompiler::CompileOptimized(const Function& function) { |
| 1501 Add(function); | 1517 Add(function); |
| 1502 } | 1518 } |
| 1503 | 1519 |
| 1504 | 1520 |
| 1505 void BackgroundCompiler::Add(const Function& f) const { | 1521 void BackgroundCompiler::Add(const Function& f) { |
| 1506 MonitorLocker ml(monitor_); | 1522 MonitorLocker ml(queue_monitor_); |
| 1507 CompilationWorkQueue queue(isolate_); | 1523 CompilationWorkQueue queue(isolate_); |
| 1508 queue.PushFront(f); | 1524 queue.PushFront(f); |
| 1525 set_queue_length(queue.Length()); | |
| 1509 ml.Notify(); | 1526 ml.Notify(); |
| 1510 } | 1527 } |
| 1511 | 1528 |
| 1512 | 1529 |
| 1513 RawFunction* BackgroundCompiler::RemoveOrNull() const { | 1530 RawFunction* BackgroundCompiler::RemoveOrNull() { |
| 1514 MonitorLocker ml(monitor_); | 1531 MonitorLocker ml(queue_monitor_); |
| 1515 CompilationWorkQueue queue(isolate_); | 1532 CompilationWorkQueue queue(isolate_); |
| 1516 return queue.IsEmpty() ? Function::null() : queue.PopBack(); | 1533 if (queue.IsEmpty()) return Function::null(); |
| 1534 set_queue_length(queue.Length() - 1); | |
| 1535 return queue.PopBack(); | |
| 1517 } | 1536 } |
| 1518 | 1537 |
| 1519 | 1538 |
| 1539 RawFunction* BackgroundCompiler::LastOrNull() const { | |
| 1540 MonitorLocker ml(queue_monitor_); | |
| 1541 CompilationWorkQueue queue(isolate_); | |
| 1542 return queue.IsEmpty() ? Function::null() : queue.Last(); | |
| 1543 } | |
| 1544 | |
| 1545 | |
| 1520 void BackgroundCompiler::Stop(BackgroundCompiler* task) { | 1546 void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
| 1521 if (task == NULL) { | 1547 if (task == NULL) { |
| 1522 return; | 1548 return; |
| 1523 } | 1549 } |
| 1524 Monitor* monitor = task->monitor_; | 1550 Monitor* monitor = task->queue_monitor_; |
| 1525 Monitor* done_monitor = task->done_monitor_; | 1551 Monitor* done_monitor = task->done_monitor_; |
| 1526 bool* task_done = task->done_; | 1552 bool* task_done = task->done_; |
| 1527 // Wake up compiler task and stop it. | 1553 // Wake up compiler task and stop it. |
| 1528 { | 1554 { |
| 1529 MonitorLocker ml(task->monitor_); | 1555 MonitorLocker ml(task->queue_monitor_); |
| 1530 task->running_ = false; | 1556 task->running_ = false; |
| 1531 // 'task' will be deleted by thread pool. | 1557 // 'task' will be deleted by thread pool. |
| 1532 task = NULL; | 1558 task = NULL; |
| 1533 ml.Notify(); | 1559 ml.Notify(); // Stop waiting for the queue. |
| 1534 } | 1560 } |
| 1535 | 1561 |
| 1536 { | 1562 { |
| 1537 MonitorLocker ml_done(done_monitor); | 1563 MonitorLocker ml_done(done_monitor); |
| 1538 while (!(*task_done)) { | 1564 while (!(*task_done)) { |
| 1539 ml_done.Wait(); | 1565 ml_done.Wait(); |
| 1540 } | 1566 } |
| 1541 } | 1567 } |
| 1542 delete task_done; | 1568 delete task_done; |
| 1543 delete done_monitor; | 1569 delete done_monitor; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1556 isolate->current_zone(), GrowableObjectArray::New())); | 1582 isolate->current_zone(), GrowableObjectArray::New())); |
| 1557 start_task = true; | 1583 start_task = true; |
| 1558 } | 1584 } |
| 1559 } | 1585 } |
| 1560 if (start_task) { | 1586 if (start_task) { |
| 1561 Dart::thread_pool()->Run(isolate->background_compiler()); | 1587 Dart::thread_pool()->Run(isolate->background_compiler()); |
| 1562 } | 1588 } |
| 1563 } | 1589 } |
| 1564 | 1590 |
| 1565 } // namespace dart | 1591 } // namespace dart |
| OLD | NEW |