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 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 |