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 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 |
OLD | NEW |