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 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 const Object& result = | 1459 const Object& result = |
1460 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1460 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
1461 isolate->object_store()->clear_sticky_error(); | 1461 isolate->object_store()->clear_sticky_error(); |
1462 return result.raw(); | 1462 return result.raw(); |
1463 } | 1463 } |
1464 UNREACHABLE(); | 1464 UNREACHABLE(); |
1465 return Object::null(); | 1465 return Object::null(); |
1466 } | 1466 } |
1467 | 1467 |
1468 | 1468 |
1469 // A simple work queue containing functions to be optimized or code generated. | 1469 // C-heap allocated background compilation queue element. |
1470 // Use PushFrontFunction and PopBackFunction to add and remove from the function | 1470 class QueueElement { |
1471 // queue and PushBackCode and PopBackCode to add and remove from the code queue. | |
1472 // TODO(srdjan): Write a more efficient implementation. | |
1473 class CompilationWorkQueue : public ValueObject { | |
1474 public: | 1471 public: |
1475 explicit CompilationWorkQueue(GrowableObjectArray* data) : data_(data) {} | 1472 explicit QueueElement(const Function& function) |
| 1473 : next_(NULL), |
| 1474 obj_(function.raw()), |
| 1475 cha_invalidation_gen_(Isolate::kInvalidGen), |
| 1476 field_invalidation_gen_(Isolate::kInvalidGen), |
| 1477 prefix_invalidation_gen_(Isolate::kInvalidGen) { |
| 1478 ASSERT(Thread::Current()->IsMutatorThread()); |
| 1479 } |
1476 | 1480 |
1477 intptr_t IsEmpty() const { return data_->Length() == 0; } | 1481 ~QueueElement() { |
1478 intptr_t Length() const { return data_->Length(); } | 1482 ASSERT(Thread::Current()->IsMutatorThread()); |
| 1483 obj_ = Object::null(); |
| 1484 } |
1479 | 1485 |
1480 void PushFrontFunction(const Function& function) { PushFront(function); } | 1486 void Clear() { |
1481 RawFunction* PopBackFunction() { return Function::RawCast(PopBack()); } | 1487 next_ = NULL; |
1482 RawFunction* LastFunction() { return Function::RawCast(Last()); } | 1488 obj_ = Object::null(); |
| 1489 cha_invalidation_gen_ = Isolate::kInvalidGen; |
| 1490 field_invalidation_gen_ = Isolate::kInvalidGen; |
| 1491 prefix_invalidation_gen_ = Isolate::kInvalidGen; |
| 1492 } |
1483 | 1493 |
1484 void PushBackCode(const Code& code) { PushBack(code); } | 1494 RawFunction* Function() const { return Function::RawCast(obj_); } |
1485 void PushBackInteger(const Integer& value) { PushBack(value); } | 1495 RawCode* Code() const { |
1486 RawCode* PopBackCode() { return Code::RawCast(PopBack()); } | 1496 return (obj_ == Object::null()) ? Code::null() : Code::RawCast(obj_); |
1487 RawInteger* PopBackInteger() { | 1497 } |
1488 Object& o = Object::Handle(PopBack()); | 1498 |
1489 if (o.IsNull()) { | 1499 uint32_t cha_invalidation_gen() const { return cha_invalidation_gen_; } |
1490 return Integer::null(); | 1500 uint32_t field_invalidation_gen() const { return field_invalidation_gen_; } |
1491 } else { | 1501 uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; } |
1492 return Integer::Cast(o).raw(); | 1502 |
| 1503 void set_next(QueueElement* elem) { next_ = elem; } |
| 1504 QueueElement* next() const { return next_; } |
| 1505 |
| 1506 RawObject** obj_ptr() { return &obj_; } |
| 1507 RawObject* obj() const { return obj_; } |
| 1508 |
| 1509 void SetFromResult(const BackgroundCompilationResult& value) { |
| 1510 ASSERT(!value.result_code().IsNull()); |
| 1511 obj_ = value.result_code().raw(); |
| 1512 cha_invalidation_gen_ = value.cha_invalidation_gen(); |
| 1513 field_invalidation_gen_ = value.field_invalidation_gen(); |
| 1514 prefix_invalidation_gen_ = value.prefix_invalidation_gen(); |
| 1515 } |
| 1516 |
| 1517 private: |
| 1518 QueueElement* next_; |
| 1519 |
| 1520 RawObject* obj_; // Code or Function. |
| 1521 uint32_t cha_invalidation_gen_; |
| 1522 uint32_t field_invalidation_gen_; |
| 1523 uint32_t prefix_invalidation_gen_; |
| 1524 |
| 1525 DISALLOW_COPY_AND_ASSIGN(QueueElement); |
| 1526 }; |
| 1527 |
| 1528 |
| 1529 // Allocated in C-heap. Handles both input and output of background compilation. |
| 1530 // It implements a FIFO queue, using Peek, Add, Remove operations. |
| 1531 class BackgroundCompilationQueue { |
| 1532 public: |
| 1533 BackgroundCompilationQueue() : first_(NULL), last_(NULL) {} |
| 1534 ~BackgroundCompilationQueue() { |
| 1535 while (!IsEmpty()) { |
| 1536 QueueElement* e = Remove(); |
| 1537 delete e; |
| 1538 } |
| 1539 ASSERT((first_ == NULL) && (last_ == NULL)); |
| 1540 } |
| 1541 |
| 1542 void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
| 1543 ASSERT(visitor != NULL); |
| 1544 QueueElement* p = first_; |
| 1545 while (p != NULL) { |
| 1546 visitor->VisitPointer(p->obj_ptr()); |
| 1547 p = p->next(); |
1493 } | 1548 } |
1494 } | 1549 } |
1495 | 1550 |
1496 private: | 1551 bool IsEmpty() const { return first_ == NULL; } |
1497 // Adds to the queue only if 'function' is not already in there. | 1552 |
1498 void PushFront(const Object& value) { | 1553 void Add(QueueElement* value) { |
1499 for (intptr_t i = 0; i < data_->Length(); i++) { | 1554 ASSERT(value != NULL); |
1500 if (data_->At(i) == value.raw()) { | 1555 if (first_ == NULL) { |
1501 return; | 1556 first_ = value; |
1502 } | 1557 } else { |
| 1558 last_->set_next(value); |
1503 } | 1559 } |
1504 // Insert new element in front. | 1560 value->set_next(NULL); |
1505 Object& f = Object::Handle(); | 1561 last_ = value; |
1506 data_->Add(f, Heap::kOld); | |
1507 for (intptr_t i = data_->Length() - 1; i > 0; i--) { | |
1508 f = data_->At(i - 1); | |
1509 data_->SetAt(i, f); | |
1510 } | |
1511 data_->SetAt(0, value); | |
1512 } | 1562 } |
1513 | 1563 |
1514 | 1564 QueueElement* Peek() const { |
1515 void PushBack(const Object& value) { | 1565 return first_; |
1516 data_->Add(value, Heap::kOld); | |
1517 } | 1566 } |
1518 | 1567 |
1519 | 1568 RawFunction* PeekFunction() const { |
1520 RawObject* PopBack() { | 1569 QueueElement* e = Peek(); |
1521 ASSERT(!IsEmpty()); | 1570 if (e == NULL) { |
1522 Object& result = Object::Handle(); | 1571 return Function::null(); |
1523 result = data_->At(data_->Length() - 1); | 1572 } else { |
1524 data_->SetLength(data_->Length() - 1); | 1573 return e->Function(); |
1525 return result.raw(); | 1574 } |
1526 } | 1575 } |
1527 | 1576 |
1528 RawObject* Last() { | 1577 QueueElement* Remove() { |
1529 ASSERT(!IsEmpty()); | 1578 ASSERT(first_ != NULL); |
1530 return data_->At(data_->Length() - 1); | 1579 QueueElement* result = first_; |
| 1580 first_ = first_->next(); |
| 1581 if (first_ == NULL) { |
| 1582 last_ = NULL; |
| 1583 } |
| 1584 return result; |
1531 } | 1585 } |
1532 | 1586 |
1533 GrowableObjectArray* data_; | 1587 bool ContainsObj(const Object& obj) const { |
| 1588 QueueElement* p = first_; |
| 1589 while (p != NULL) { |
| 1590 if (p->obj() == obj.raw()) { |
| 1591 return true; |
| 1592 } |
| 1593 p = p->next(); |
| 1594 } |
| 1595 return false; |
| 1596 } |
1534 | 1597 |
1535 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); | 1598 private: |
| 1599 QueueElement* first_; |
| 1600 QueueElement* last_; |
| 1601 |
| 1602 DISALLOW_COPY_AND_ASSIGN(BackgroundCompilationQueue); |
1536 }; | 1603 }; |
1537 | 1604 |
1538 | 1605 |
1539 | |
1540 BackgroundCompilationResult::BackgroundCompilationResult() | 1606 BackgroundCompilationResult::BackgroundCompilationResult() |
1541 : result_code_(Code::Handle()), | 1607 : result_code_(Code::Handle()), |
1542 cha_invalidation_gen_(Integer::Handle()), | 1608 cha_invalidation_gen_(Isolate::kInvalidGen), |
1543 field_invalidation_gen_(Integer::Handle()), | 1609 field_invalidation_gen_(Isolate::kInvalidGen), |
1544 prefix_invalidation_gen_(Integer::Handle()) { | 1610 prefix_invalidation_gen_(Isolate::kInvalidGen) { |
1545 } | 1611 } |
1546 | 1612 |
1547 | 1613 |
1548 void BackgroundCompilationResult::Init() { | 1614 void BackgroundCompilationResult::Init() { |
1549 Isolate* i = Isolate::Current(); | 1615 Isolate* i = Isolate::Current(); |
1550 result_code_ = Code::null(); | 1616 result_code_ = Code::null(); |
1551 cha_invalidation_gen_ = Integer::New(i->cha_invalidation_gen(), Heap::kOld); | 1617 cha_invalidation_gen_ = i->cha_invalidation_gen(); |
1552 field_invalidation_gen_ = | 1618 field_invalidation_gen_ = i->field_invalidation_gen(); |
1553 Integer::New(i->field_invalidation_gen(), Heap::kOld); | 1619 prefix_invalidation_gen_ = i->prefix_invalidation_gen(); |
1554 prefix_invalidation_gen_ = | |
1555 Integer::New(i->prefix_invalidation_gen(), Heap::kOld); | |
1556 } | 1620 } |
1557 | 1621 |
1558 | 1622 |
| 1623 void BackgroundCompilationResult::SetFromQElement(QueueElement* value) { |
| 1624 ASSERT(value != NULL); |
| 1625 result_code_ = value->Code(); |
| 1626 cha_invalidation_gen_ = value->cha_invalidation_gen(); |
| 1627 field_invalidation_gen_ = value->field_invalidation_gen(); |
| 1628 prefix_invalidation_gen_ = value->prefix_invalidation_gen(); |
| 1629 } |
| 1630 |
| 1631 |
1559 bool BackgroundCompilationResult::IsValid() const { | 1632 bool BackgroundCompilationResult::IsValid() const { |
1560 if (result_code().IsNull() || result_code().IsDisabled()) { | 1633 if (result_code().IsNull() || result_code().IsDisabled()) { |
1561 return false; | 1634 return false; |
1562 } | 1635 } |
1563 Isolate* i = Isolate::Current(); | 1636 Isolate* i = Isolate::Current(); |
1564 if (!cha_invalidation_gen_.IsNull() && | 1637 if ((cha_invalidation_gen_ != Isolate::kInvalidGen) && |
1565 (cha_invalidation_gen_.AsInt64Value() != i->cha_invalidation_gen())) { | 1638 (cha_invalidation_gen_ != i->cha_invalidation_gen())) { |
1566 return false; | 1639 return false; |
1567 } | 1640 } |
1568 if (!field_invalidation_gen_.IsNull() && | 1641 if ((field_invalidation_gen_ != Isolate::kInvalidGen) && |
1569 (field_invalidation_gen_.AsInt64Value() != i->field_invalidation_gen())) { | 1642 (field_invalidation_gen_ != i->field_invalidation_gen())) { |
1570 return false; | 1643 return false; |
1571 } | 1644 } |
1572 if (!prefix_invalidation_gen_.IsNull() && | 1645 if ((prefix_invalidation_gen_ != Isolate::kInvalidGen) && |
1573 (prefix_invalidation_gen_.AsInt64Value() != | 1646 (prefix_invalidation_gen_ != i->prefix_invalidation_gen())) { |
1574 i->prefix_invalidation_gen())) { | |
1575 return false; | 1647 return false; |
1576 } | 1648 } |
1577 return true; | 1649 return true; |
1578 } | 1650 } |
1579 | 1651 |
1580 | 1652 |
1581 void BackgroundCompilationResult::PrintValidity() const { | 1653 void BackgroundCompilationResult::PrintValidity() const { |
1582 Object& o = Object::Handle(result_code().owner()); | 1654 Object& o = Object::Handle(result_code().owner()); |
1583 THR_Print("BackgroundCompilationResult: %s\n", | 1655 THR_Print("BackgroundCompilationResult: %s\n", |
1584 Function::Cast(o).ToQualifiedCString()); | 1656 Function::Cast(o).ToQualifiedCString()); |
1585 if (result_code().IsNull()) { | 1657 if (result_code().IsNull()) { |
1586 THR_Print(" result_code is NULL\n"); | 1658 THR_Print(" result_code is NULL\n"); |
1587 return; | 1659 return; |
1588 } | 1660 } |
1589 if (result_code().IsDisabled()) { | 1661 if (result_code().IsDisabled()) { |
1590 THR_Print(" result_code is disabled\n"); | 1662 THR_Print(" result_code is disabled\n"); |
1591 return; | 1663 return; |
1592 } | 1664 } |
1593 Isolate* i = Isolate::Current(); | 1665 Isolate* i = Isolate::Current(); |
1594 THR_Print(" cha_invalidation_gen: %s (current: %u)\n", | 1666 THR_Print(" cha_invalidation_gen: %u (current: %u)\n", |
1595 cha_invalidation_gen_.ToCString(), i->cha_invalidation_gen()); | 1667 cha_invalidation_gen_, i->cha_invalidation_gen()); |
1596 THR_Print(" field_invalidation_gen: %s (current: %u)\n", | 1668 THR_Print(" field_invalidation_gen: %u (current: %u)\n", |
1597 field_invalidation_gen_.ToCString(), i->field_invalidation_gen()); | 1669 field_invalidation_gen_, i->field_invalidation_gen()); |
1598 THR_Print(" prefix_invalidation_gen: %s (current: %u)\n", | 1670 THR_Print(" prefix_invalidation_gen: %u (current: %u)\n", |
1599 prefix_invalidation_gen_.ToCString(), i->prefix_invalidation_gen()); | 1671 prefix_invalidation_gen_, i->prefix_invalidation_gen()); |
1600 } | |
1601 | |
1602 | |
1603 void BackgroundCompilationResult::PushOnQueue( | |
1604 CompilationWorkQueue* queue) const { | |
1605 queue->PushBackCode(result_code()); | |
1606 queue->PushBackInteger(cha_invalidation_gen_); | |
1607 queue->PushBackInteger(field_invalidation_gen_); | |
1608 queue->PushBackInteger(prefix_invalidation_gen_); | |
1609 } | |
1610 | |
1611 | |
1612 void BackgroundCompilationResult::PopFromQueue(CompilationWorkQueue* queue) { | |
1613 prefix_invalidation_gen_ = queue->PopBackInteger(); | |
1614 field_invalidation_gen_ = queue->PopBackInteger(); | |
1615 cha_invalidation_gen_ = queue->PopBackInteger(); | |
1616 result_code_ = queue->PopBackCode(); | |
1617 } | 1672 } |
1618 | 1673 |
1619 | 1674 |
1620 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) | 1675 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) |
1621 : isolate_(isolate), running_(true), done_(new bool()), | 1676 : isolate_(isolate), running_(true), done_(new bool()), |
1622 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), | 1677 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), |
1623 function_queue_length_(0), | 1678 function_queue_(new BackgroundCompilationQueue()), |
1624 compilation_function_queue_(GrowableObjectArray::null()), | 1679 result_queue_(new BackgroundCompilationQueue()) { |
1625 compilation_result_queue_(GrowableObjectArray::null()) { | |
1626 *done_ = false; | 1680 *done_ = false; |
1627 } | 1681 } |
1628 | 1682 |
1629 | 1683 |
1630 void BackgroundCompiler::Run() { | 1684 void BackgroundCompiler::Run() { |
1631 while (running_) { | 1685 while (running_) { |
1632 // Maybe something is already in the queue, check first before waiting | 1686 // Maybe something is already in the queue, check first before waiting |
1633 // to be notified. | 1687 // to be notified. |
1634 Thread::EnterIsolateAsHelper(isolate_); | 1688 Thread::EnterIsolateAsHelper(isolate_); |
1635 { | 1689 { |
1636 Thread* thread = Thread::Current(); | 1690 Thread* thread = Thread::Current(); |
1637 StackZone stack_zone(thread); | 1691 StackZone stack_zone(thread); |
1638 Zone* zone = stack_zone.GetZone(); | 1692 Zone* zone = stack_zone.GetZone(); |
1639 HANDLESCOPE(thread); | 1693 HANDLESCOPE(thread); |
1640 Function& function = Function::Handle(zone); | 1694 Function& function = Function::Handle(zone); |
1641 Function& temp_function = Function::Handle(zone); | 1695 function = function_queue()->PeekFunction(); |
1642 function = LastFunctionOrNull(); | |
1643 BackgroundCompilationResult result; | 1696 BackgroundCompilationResult result; |
1644 // Finish all compilation before exiting (even if running_ is changed to | 1697 while (running_ && !function.IsNull()) { |
1645 // false). | |
1646 while (!function.IsNull()) { | |
1647 result.Init(); | 1698 result.Init(); |
1648 const Error& error = Error::Handle(zone, | 1699 const Error& error = Error::Handle(zone, |
1649 Compiler::CompileOptimizedFunction(thread, | 1700 Compiler::CompileOptimizedFunction(thread, |
1650 function, | 1701 function, |
1651 Compiler::kNoOSRDeoptId, | 1702 Compiler::kNoOSRDeoptId, |
1652 &result)); | 1703 &result)); |
1653 // TODO(srdjan): We do not expect errors while compiling optimized | 1704 // TODO(srdjan): We do not expect errors while compiling optimized |
1654 // code, any errors should have been caught when compiling | 1705 // code, any errors should have been caught when compiling |
1655 // unoptimized code. | 1706 // unoptimized code. |
1656 // If it still happens mark function as not optimizable. | 1707 // If it still happens mark function as not optimizable. |
1657 ASSERT(error.IsNull()); | 1708 ASSERT(error.IsNull()); |
1658 temp_function = RemoveFunctionOrNull(); | 1709 // Reuse the input QueueElement to return the result. |
1659 ASSERT(temp_function.raw() == function.raw()); | 1710 QueueElement* qelem = function_queue()->Remove(); |
1660 function = LastFunctionOrNull(); | 1711 qelem->Clear(); |
1661 ASSERT(!result.result_code().IsNull()); | 1712 result_queue()->Add(qelem); |
1662 AddResult(result); | 1713 // Add 'qelem' to the queue first so that it gets visited by GC. |
| 1714 qelem->SetFromResult(result); |
| 1715 function = function_queue()->PeekFunction(); |
1663 } | 1716 } |
1664 } | 1717 } |
1665 Thread::ExitIsolateAsHelper(); | 1718 Thread::ExitIsolateAsHelper(); |
1666 { | 1719 { |
1667 // Wait to be notified when the work queue is not empty. | 1720 // Wait to be notified when the work queue is not empty. |
1668 MonitorLocker ml(queue_monitor_); | 1721 MonitorLocker ml(queue_monitor_); |
1669 while ((function_queue_length() == 0) && running_) { | 1722 while (function_queue()->IsEmpty() && running_) { |
1670 ml.Wait(); | 1723 ml.Wait(); |
1671 } | 1724 } |
1672 } | 1725 } |
1673 } // while running | 1726 } // while running |
1674 | 1727 |
1675 compilation_function_queue_ = GrowableObjectArray::null(); | |
1676 compilation_result_queue_ = GrowableObjectArray::null(); | |
1677 { | 1728 { |
1678 // Notify that the thread is done. | 1729 // Notify that the thread is done. |
1679 MonitorLocker ml_done(done_monitor_); | 1730 MonitorLocker ml_done(done_monitor_); |
1680 *done_ = true; | 1731 *done_ = true; |
1681 ml_done.Notify(); | 1732 ml_done.Notify(); |
1682 } | 1733 } |
1683 } | 1734 } |
1684 | 1735 |
1685 | 1736 |
1686 void BackgroundCompiler::CompileOptimized(const Function& function) { | 1737 void BackgroundCompiler::CompileOptimized(const Function& function) { |
1687 AddFunction(function); | 1738 ASSERT(Thread::Current()->IsMutatorThread()); |
| 1739 MonitorLocker ml(queue_monitor_); |
| 1740 if (function_queue()->ContainsObj(function)) { |
| 1741 return; |
| 1742 } |
| 1743 QueueElement* elem = new QueueElement(function); |
| 1744 function_queue()->Add(elem); |
| 1745 ml.Notify(); |
1688 } | 1746 } |
1689 | 1747 |
1690 | 1748 |
1691 void BackgroundCompiler::InstallGeneratedCode() { | 1749 void BackgroundCompiler::InstallGeneratedCode() { |
1692 ASSERT(Thread::Current()->IsMutatorThread()); | 1750 ASSERT(Thread::Current()->IsMutatorThread()); |
1693 MonitorLocker ml(queue_monitor_); | 1751 MonitorLocker ml(queue_monitor_); |
1694 CompilationWorkQueue queue(ResultQueue()); | |
1695 Object& owner = Object::Handle(); | 1752 Object& owner = Object::Handle(); |
1696 for (intptr_t i = 0; i < queue.Length(); i++) { | 1753 while (result_queue()->Peek() != NULL) { |
1697 BackgroundCompilationResult result; | 1754 BackgroundCompilationResult result; |
1698 result.PopFromQueue(&queue); | 1755 QueueElement* elem = result_queue()->Remove(); |
| 1756 ASSERT(elem != NULL); |
| 1757 result.SetFromQElement(elem); |
| 1758 delete elem; |
| 1759 |
1699 owner = result.result_code().owner(); | 1760 owner = result.result_code().owner(); |
1700 const Function& function = Function::Cast(owner); | 1761 const Function& function = Function::Cast(owner); |
1701 if (result.IsValid()) { | 1762 if (result.IsValid()) { |
1702 function.InstallOptimizedCode(result.result_code(), false /* not OSR */); | 1763 function.InstallOptimizedCode(result.result_code(), false /* not OSR */); |
1703 } else if (FLAG_trace_compiler) { | 1764 } else if (FLAG_trace_compiler) { |
1704 THR_Print("Drop code generated in the background compiler:\n"); | 1765 THR_Print("Drop code generated in the background compiler:\n"); |
1705 result.PrintValidity(); | 1766 result.PrintValidity(); |
1706 } | 1767 } |
1707 if (function.usage_counter() < 0) { | 1768 if (function.usage_counter() < 0) { |
1708 // Reset to 0 so that it can be recompiled if needed. | 1769 // Reset to 0 so that it can be recompiled if needed. |
1709 function.set_usage_counter(0); | 1770 function.set_usage_counter(0); |
1710 } | 1771 } |
1711 } | 1772 } |
1712 } | 1773 } |
1713 | 1774 |
1714 | 1775 |
1715 GrowableObjectArray* BackgroundCompiler::FunctionsQueue() const { | |
1716 return &GrowableObjectArray::ZoneHandle(compilation_function_queue_); | |
1717 } | |
1718 | |
1719 | |
1720 GrowableObjectArray* BackgroundCompiler::ResultQueue() const { | |
1721 return &GrowableObjectArray::ZoneHandle(compilation_result_queue_); | |
1722 } | |
1723 | |
1724 | |
1725 void BackgroundCompiler::AddFunction(const Function& f) { | |
1726 MonitorLocker ml(queue_monitor_); | |
1727 CompilationWorkQueue queue(FunctionsQueue()); | |
1728 queue.PushFrontFunction(f); | |
1729 set_function_queue_length(queue.Length()); | |
1730 // Notify waiting background compiler task. | |
1731 ml.Notify(); | |
1732 } | |
1733 | |
1734 | |
1735 RawFunction* BackgroundCompiler::RemoveFunctionOrNull() { | |
1736 MonitorLocker ml(queue_monitor_); | |
1737 CompilationWorkQueue queue(FunctionsQueue()); | |
1738 if (queue.IsEmpty()) return Function::null(); | |
1739 set_function_queue_length(queue.Length() - 1); | |
1740 return queue.PopBackFunction(); | |
1741 } | |
1742 | |
1743 | |
1744 RawFunction* BackgroundCompiler::LastFunctionOrNull() const { | |
1745 MonitorLocker ml(queue_monitor_); | |
1746 CompilationWorkQueue queue(FunctionsQueue()); | |
1747 return queue.IsEmpty() ? Function::null() : queue.LastFunction(); | |
1748 } | |
1749 | |
1750 | |
1751 void BackgroundCompiler::AddResult(const BackgroundCompilationResult& value) { | |
1752 MonitorLocker ml(queue_monitor_); | |
1753 CompilationWorkQueue queue(ResultQueue()); | |
1754 value.PushOnQueue(&queue); | |
1755 } | |
1756 | |
1757 | |
1758 void BackgroundCompiler::set_compilation_function_queue( | |
1759 const GrowableObjectArray& value) { | |
1760 compilation_function_queue_ = value.raw(); | |
1761 } | |
1762 | |
1763 | |
1764 void BackgroundCompiler::set_compilation_result_queue( | |
1765 const GrowableObjectArray& value) { | |
1766 compilation_result_queue_ = value.raw(); | |
1767 } | |
1768 | |
1769 | |
1770 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) { | 1776 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) { |
1771 visitor->VisitPointer(reinterpret_cast<RawObject**>( | 1777 function_queue_->VisitObjectPointers(visitor); |
1772 &compilation_function_queue_)); | 1778 result_queue_->VisitObjectPointers(visitor); |
1773 | |
1774 visitor->VisitPointer(reinterpret_cast<RawObject**>( | |
1775 &compilation_result_queue_)); | |
1776 } | 1779 } |
1777 | 1780 |
1778 | 1781 |
1779 void BackgroundCompiler::Stop(BackgroundCompiler* task) { | 1782 void BackgroundCompiler::Stop(BackgroundCompiler* task) { |
1780 ASSERT(Isolate::Current()->background_compiler() == task); | 1783 ASSERT(Isolate::Current()->background_compiler() == task); |
1781 if (task == NULL) { | 1784 if (task == NULL) { |
1782 return; | 1785 return; |
1783 } | 1786 } |
| 1787 BackgroundCompilationQueue* function_queue = task->function_queue(); |
| 1788 BackgroundCompilationQueue* result_queue = task->result_queue(); |
| 1789 |
1784 Monitor* queue_monitor = task->queue_monitor_; | 1790 Monitor* queue_monitor = task->queue_monitor_; |
1785 Monitor* done_monitor = task->done_monitor_; | 1791 Monitor* done_monitor = task->done_monitor_; |
1786 bool* task_done = task->done_; | 1792 bool* task_done = task->done_; |
1787 // Wake up compiler task and stop it. | 1793 // Wake up compiler task and stop it. |
1788 { | 1794 { |
1789 MonitorLocker ml(task->queue_monitor_); | 1795 MonitorLocker ml(task->queue_monitor_); |
1790 task->running_ = false; | 1796 task->running_ = false; |
1791 // 'task' will be deleted by thread pool. | 1797 // 'task' will be deleted by thread pool. |
1792 task = NULL; | 1798 task = NULL; |
1793 ml.Notify(); // Stop waiting for the queue. | 1799 ml.Notify(); // Stop waiting for the queue. |
1794 } | 1800 } |
1795 | 1801 |
1796 { | 1802 { |
1797 MonitorLocker ml_done(done_monitor); | 1803 MonitorLocker ml_done(done_monitor); |
1798 while (!(*task_done)) { | 1804 while (!(*task_done)) { |
1799 ml_done.Wait(); | 1805 ml_done.Wait(); |
1800 } | 1806 } |
1801 } | 1807 } |
1802 delete task_done; | 1808 delete task_done; |
1803 delete done_monitor; | 1809 delete done_monitor; |
1804 delete queue_monitor; | 1810 delete queue_monitor; |
| 1811 delete function_queue; |
| 1812 delete result_queue; |
1805 Isolate::Current()->set_background_compiler(NULL); | 1813 Isolate::Current()->set_background_compiler(NULL); |
1806 } | 1814 } |
1807 | 1815 |
1808 | 1816 |
1809 void BackgroundCompiler::EnsureInit(Thread* thread) { | 1817 void BackgroundCompiler::EnsureInit(Thread* thread) { |
1810 bool start_task = false; | 1818 bool start_task = false; |
1811 Isolate* isolate = thread->isolate(); | 1819 Isolate* isolate = thread->isolate(); |
1812 { | 1820 { |
1813 MutexLocker ml(isolate->mutex()); | 1821 MutexLocker ml(isolate->mutex()); |
1814 if (isolate->background_compiler() == NULL) { | 1822 if (isolate->background_compiler() == NULL) { |
1815 BackgroundCompiler* task = new BackgroundCompiler(isolate); | 1823 BackgroundCompiler* task = new BackgroundCompiler(isolate); |
1816 isolate->set_background_compiler(task); | 1824 isolate->set_background_compiler(task); |
1817 // TODO(srdjan): Temporary fix to prevent growing (and thus GC-ing) of | |
1818 // queues while inside a MonitorLocker. Will replace GrowableObjectArray | |
1819 // with C heap allocated linked list. | |
1820 GrowableObjectArray& a = GrowableObjectArray::Handle( | |
1821 thread->zone(), GrowableObjectArray::New(Heap::kOld)); | |
1822 a.Grow(1000, Heap::kOld); | |
1823 task->set_compilation_function_queue(a); | |
1824 | |
1825 a = GrowableObjectArray::New(Heap::kOld); | |
1826 a.Grow(1000, Heap::kOld); | |
1827 task->set_compilation_result_queue(a); | |
1828 start_task = true; | 1825 start_task = true; |
1829 } | 1826 } |
1830 } | 1827 } |
1831 if (start_task) { | 1828 if (start_task) { |
1832 Dart::thread_pool()->Run(isolate->background_compiler()); | 1829 Dart::thread_pool()->Run(isolate->background_compiler()); |
1833 } | 1830 } |
1834 } | 1831 } |
1835 | 1832 |
1836 } // namespace dart | 1833 } // namespace dart |
OLD | NEW |