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 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 Isolate* const isolate = thread->isolate(); | 1395 Isolate* const isolate = thread->isolate(); |
1396 const Object& result = | 1396 const Object& result = |
1397 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1397 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
1398 isolate->object_store()->clear_sticky_error(); | 1398 isolate->object_store()->clear_sticky_error(); |
1399 return result.raw(); | 1399 return result.raw(); |
1400 } | 1400 } |
1401 UNREACHABLE(); | 1401 UNREACHABLE(); |
1402 return Object::null(); | 1402 return Object::null(); |
1403 } | 1403 } |
1404 | 1404 |
| 1405 |
| 1406 // A simple work queue containing functions to be optimized. Use |
| 1407 // PushFront and PopBack to add and read from queue. |
| 1408 // TODO(srdjan): Write a more efficient implementation. |
| 1409 class CompilationWorkQueue : public ValueObject { |
| 1410 public: |
| 1411 explicit CompilationWorkQueue(Isolate* isolate) : |
| 1412 data_(GrowableObjectArray::Handle()) { |
| 1413 data_ = isolate->background_compilation_queue(); |
| 1414 } |
| 1415 |
| 1416 intptr_t IsEmpty() const { return data_.Length() == 0; } |
| 1417 |
| 1418 // Adds to the queue only if 'function' is not already in there. |
| 1419 void PushFront(const Function& function) { |
| 1420 for (intptr_t i = 0; i < data_.Length(); i++) { |
| 1421 if (data_.At(i) == function.raw()) { |
| 1422 return; |
| 1423 } |
| 1424 } |
| 1425 // Insert new element in front. |
| 1426 Object& f = Object::Handle(); |
| 1427 data_.Add(f); |
| 1428 for (intptr_t i = data_.Length() - 1; i > 0; i--) { |
| 1429 f = data_.At(i - 1); |
| 1430 data_.SetAt(i, f); |
| 1431 } |
| 1432 data_.SetAt(0, function); |
| 1433 } |
| 1434 |
| 1435 RawFunction* PopBack() { |
| 1436 ASSERT(!IsEmpty()); |
| 1437 Object& result = Object::Handle(); |
| 1438 result = data_.At(data_.Length() - 1); |
| 1439 data_.SetLength(data_.Length() - 1); |
| 1440 return Function::Cast(result).raw(); |
| 1441 } |
| 1442 |
| 1443 private: |
| 1444 GrowableObjectArray& data_; |
| 1445 |
| 1446 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); |
| 1447 }; |
| 1448 |
| 1449 |
| 1450 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
| 1451 : isolate_(isolate), running_(true), done_(new bool()), |
| 1452 monitor_(new Monitor()), done_monitor_(new Monitor()) { |
| 1453 *done_ = false; |
| 1454 } |
| 1455 |
| 1456 |
| 1457 void BackgroundCompiler::Run() { |
| 1458 while (running_) { |
| 1459 { |
| 1460 // Wait to be notified when the work queue is not empty. |
| 1461 MonitorLocker ml(monitor_); |
| 1462 ml.Wait(); |
| 1463 } |
| 1464 |
| 1465 Thread::EnterIsolateAsHelper(isolate_); |
| 1466 { |
| 1467 Thread* thread = Thread::Current(); |
| 1468 StackZone stack_zone(thread); |
| 1469 HANDLESCOPE(thread); |
| 1470 Function& function = Function::Handle(); |
| 1471 function = RemoveOrNull(); |
| 1472 while (!function.IsNull()) { |
| 1473 if (true) { |
| 1474 // Debugging printing |
| 1475 THR_Print("Background compilation: %s\n", |
| 1476 function.ToQualifiedCString()); |
| 1477 } else { |
| 1478 const Error& error = Error::Handle( |
| 1479 Compiler::CompileOptimizedFunction(thread, function)); |
| 1480 // TODO(srdjan): We do not expect errors while compiling optimized |
| 1481 // code, any errors should have been caught when compiling |
| 1482 // unotpimized code. |
| 1483 // If it still happens mark function as not optimizable. |
| 1484 ASSERT(error.IsNull()); |
| 1485 } |
| 1486 function = RemoveOrNull(); |
| 1487 } |
| 1488 } |
| 1489 Thread::ExitIsolateAsHelper(); |
| 1490 } |
| 1491 { |
| 1492 // Notify that the thread is done. |
| 1493 MonitorLocker ml_done(done_monitor_); |
| 1494 *done_ = true; |
| 1495 ml_done.Notify(); |
| 1496 } |
| 1497 } |
| 1498 |
| 1499 |
| 1500 void BackgroundCompiler::CompileOptimized(const Function& function) { |
| 1501 Add(function); |
| 1502 } |
| 1503 |
| 1504 |
| 1505 void BackgroundCompiler::Add(const Function& f) const { |
| 1506 MonitorLocker ml(monitor_); |
| 1507 CompilationWorkQueue queue(isolate_); |
| 1508 queue.PushFront(f); |
| 1509 ml.Notify(); |
| 1510 } |
| 1511 |
| 1512 |
| 1513 RawFunction* BackgroundCompiler::RemoveOrNull() const { |
| 1514 MonitorLocker ml(monitor_); |
| 1515 CompilationWorkQueue queue(isolate_); |
| 1516 return queue.IsEmpty() ? Function::null() : queue.PopBack(); |
| 1517 } |
| 1518 |
| 1519 |
| 1520 void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
| 1521 if (task == NULL) { |
| 1522 return; |
| 1523 } |
| 1524 Monitor* monitor = task->monitor_; |
| 1525 Monitor* done_monitor = task->done_monitor_; |
| 1526 bool* task_done = task->done_; |
| 1527 // Wake up compiler task and stop it. |
| 1528 { |
| 1529 MonitorLocker ml(task->monitor_); |
| 1530 task->running_ = false; |
| 1531 // 'task' will be deleted by thread pool. |
| 1532 task = NULL; |
| 1533 ml.Notify(); |
| 1534 } |
| 1535 |
| 1536 { |
| 1537 MonitorLocker ml_done(done_monitor); |
| 1538 while (!(*task_done)) { |
| 1539 ml_done.Wait(); |
| 1540 } |
| 1541 } |
| 1542 delete task_done; |
| 1543 delete done_monitor; |
| 1544 delete monitor; |
| 1545 } |
| 1546 |
| 1547 |
| 1548 void BackgroundCompiler::EnsureInit(Isolate* isolate) { |
| 1549 bool start_task = false; |
| 1550 { |
| 1551 MutexLocker ml(isolate->mutex()); |
| 1552 if (isolate->background_compiler() == NULL) { |
| 1553 BackgroundCompiler* task = new BackgroundCompiler(isolate); |
| 1554 isolate->set_background_compiler(task); |
| 1555 isolate->set_background_compilation_queue( |
| 1556 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New())); |
| 1557 start_task = true; |
| 1558 } |
| 1559 } |
| 1560 if (start_task) { |
| 1561 Dart::thread_pool()->Run(isolate->background_compiler()); |
| 1562 } |
| 1563 } |
| 1564 |
1405 } // namespace dart | 1565 } // namespace dart |
OLD | NEW |