Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: runtime/vm/compiler.cc

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

Powered by Google App Engine
This is Rietveld 408576698