Chromium Code Reviews| Index: runtime/vm/pages.cc |
| =================================================================== |
| --- runtime/vm/pages.cc (revision 39381) |
| +++ runtime/vm/pages.cc (working copy) |
| @@ -8,7 +8,9 @@ |
| #include "vm/compiler_stats.h" |
| #include "vm/gc_marker.h" |
| #include "vm/gc_sweeper.h" |
| +#include "vm/lockers.h" |
| #include "vm/object.h" |
| +#include "vm/thread.h" |
| #include "vm/virtual_memory.h" |
| namespace dart { |
| @@ -31,7 +33,6 @@ |
| "Emit a log message when pointers to unused code are dropped."); |
| DEFINE_FLAG(bool, always_drop_code, false, |
| "Always try to drop code if the function's usage counter is >= 0"); |
| -DECLARE_FLAG(bool, write_protect_code); |
| HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { |
| ASSERT(memory->size() > VirtualMemory::PageSize()); |
| @@ -124,7 +125,8 @@ |
| pages_tail_(NULL), |
| large_pages_(NULL), |
| max_capacity_in_words_(max_capacity_in_words), |
| - sweeping_(false), |
| + tasks_lock_(new Monitor()), |
| + tasks_(0), |
| page_space_controller_(heap, |
| FLAG_heap_growth_space_ratio, |
| FLAG_heap_growth_rate, |
| @@ -135,8 +137,13 @@ |
| PageSpace::~PageSpace() { |
| + { |
| + MonitorLocker ml(tasks_lock()); |
| + ASSERT(tasks() == 0); |
|
siva
2014/08/20 17:21:22
seems weird that a monitor locker is being done ju
Ivan Posva
2014/08/20 18:35:20
{
MonitorLocker ml(tasks_lock());
while(ta
|
| + } |
| FreePages(pages_); |
| FreePages(large_pages_); |
| + delete tasks_lock_; |
| } |
| @@ -238,18 +245,22 @@ |
| } |
| -uword PageSpace::TryAllocate(intptr_t size, |
| - HeapPage::PageType type, |
| - GrowthPolicy growth_policy) { |
| +uword PageSpace::TryAllocateInternal(intptr_t size, |
| + HeapPage::PageType type, |
| + GrowthPolicy growth_policy, |
| + bool is_protected, |
| + bool is_locked) { |
| ASSERT(size >= kObjectAlignment); |
| ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
| uword result = 0; |
| SpaceUsage after_allocation = usage_; |
| after_allocation.used_in_words += size >> kWordSizeLog2; |
| if (size < kAllocatablePageSize) { |
| - const bool is_protected = (type == HeapPage::kExecutable) |
| - && FLAG_write_protect_code; |
| - result = freelist_[type].TryAllocate(size, is_protected); |
| + if (is_locked) { |
| + result = freelist_[type].TryAllocateLocked(size, is_protected); |
| + } else { |
| + result = freelist_[type].TryAllocate(size, is_protected); |
| + } |
| if (result == 0) { |
| // Can we grow by one page? |
| after_allocation.capacity_in_words += kPageSizeInWords; |
| @@ -264,7 +275,11 @@ |
| uword free_start = result + size; |
| intptr_t free_size = page->object_end() - free_start; |
| if (free_size > 0) { |
| - freelist_[type].Free(free_start, free_size); |
| + if (is_locked) { |
| + freelist_[type].FreeLocked(free_start, free_size); |
| + } else { |
| + freelist_[type].Free(free_start, free_size); |
| + } |
| } |
| } |
| } |
| @@ -296,6 +311,16 @@ |
| } |
| + void PageSpace::AcquireDataLock() { |
| + freelist_[HeapPage::kData].mutex()->Lock(); |
| + } |
| + |
| + |
| + void PageSpace::ReleaseDataLock() { |
| + freelist_[HeapPage::kData].mutex()->Unlock(); |
| + } |
| + |
| + |
| void PageSpace::AllocateExternal(intptr_t size) { |
| intptr_t size_in_words = size >> kWordSizeLog2; |
| usage_.external_in_words += size_in_words; |
| @@ -491,11 +516,18 @@ |
| void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
| - // MarkSweep is not reentrant. Make sure that is the case. |
| - ASSERT(!sweeping_); |
| - sweeping_ = true; |
| - Isolate* isolate = Isolate::Current(); |
| + Isolate* isolate = heap_->isolate(); |
| + ASSERT(isolate == Isolate::Current()); |
| + // Wait for pending tasks to complete and then account for the driver task. |
| + { |
| + MonitorLocker locker(tasks_lock()); |
| + while (tasks() != 0) { |
| + locker.Wait(); |
| + } |
| + set_tasks(1); |
| + } |
| + |
| NoHandleScope no_handles(isolate); |
| if (FLAG_print_free_list_before_gc) { |
| @@ -594,9 +626,12 @@ |
| OS::PrintErr(" done.\n"); |
| } |
| - // Done, reset the marker. |
| - ASSERT(sweeping_); |
| - sweeping_ = false; |
| + // Done, reset the task count. |
| + { |
| + MonitorLocker locker(tasks_lock()); |
|
siva
2014/08/20 17:21:22
MutexLocker is sufficient here (no wait or notify
Ivan Posva
2014/08/20 18:35:20
MutexLocker does not work with Monitors.
{
|
| + ASSERT(tasks() == 1); |
| + set_tasks(tasks() - 1); |
| + } |
| } |