| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/gc_sweeper.h" | 5 #include "vm/gc_sweeper.h" |
| 6 | 6 |
| 7 #include "vm/freelist.h" | 7 #include "vm/freelist.h" |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/lockers.h" | 10 #include "vm/lockers.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 uword start = page->object_start(); | 21 uword start = page->object_start(); |
| 22 uword end = page->object_end(); | 22 uword end = page->object_end(); |
| 23 uword current = start; | 23 uword current = start; |
| 24 | 24 |
| 25 while (current < end) { | 25 while (current < end) { |
| 26 intptr_t obj_size; | 26 intptr_t obj_size; |
| 27 RawObject* raw_obj = RawObject::FromAddr(current); | 27 RawObject* raw_obj = RawObject::FromAddr(current); |
| 28 if (raw_obj->IsMarked()) { | 28 if (raw_obj->IsMarked()) { |
| 29 // Found marked object. Clear the mark bit and update swept bytes. | 29 // Found marked object. Clear the mark bit and update swept bytes. |
| 30 raw_obj->ClearMarkBit(); | 30 raw_obj->ClearMarkBit(); |
| 31 obj_size = raw_obj->Size(); | 31 obj_size = raw_obj->Size(class_table_); |
| 32 in_use = true; | 32 in_use = true; |
| 33 } else { | 33 } else { |
| 34 uword free_end = current + raw_obj->Size(); | 34 uword free_end = current + raw_obj->Size(class_table_); |
| 35 while (free_end < end) { | 35 while (free_end < end) { |
| 36 RawObject* next_obj = RawObject::FromAddr(free_end); | 36 RawObject* next_obj = RawObject::FromAddr(free_end); |
| 37 if (next_obj->IsMarked()) { | 37 if (next_obj->IsMarked()) { |
| 38 // Reached the end of the free block. | 38 // Reached the end of the free block. |
| 39 break; | 39 break; |
| 40 } | 40 } |
| 41 // Expand the free block by the size of this object. | 41 // Expand the free block by the size of this object. |
| 42 free_end += next_obj->Size(); | 42 free_end += next_obj->Size(class_table_); |
| 43 } | 43 } |
| 44 obj_size = free_end - current; | 44 obj_size = free_end - current; |
| 45 if (is_executable) { | 45 if (is_executable) { |
| 46 memset(reinterpret_cast<void*>(current), 0xcc, obj_size); | 46 memset(reinterpret_cast<void*>(current), 0xcc, obj_size); |
| 47 } else { | 47 } else { |
| 48 #if defined(DEBUG) | 48 #if defined(DEBUG) |
| 49 memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size); | 49 memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size); |
| 50 #endif // DEBUG | 50 #endif // DEBUG |
| 51 } | 51 } |
| 52 if ((current != start) || (free_end != end)) { | 52 if ((current != start) || (free_end != end)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 64 | 64 |
| 65 return in_use; | 65 return in_use; |
| 66 } | 66 } |
| 67 | 67 |
| 68 | 68 |
| 69 intptr_t GCSweeper::SweepLargePage(HeapPage* page) { | 69 intptr_t GCSweeper::SweepLargePage(HeapPage* page) { |
| 70 intptr_t words_to_end = 0; | 70 intptr_t words_to_end = 0; |
| 71 RawObject* raw_obj = RawObject::FromAddr(page->object_start()); | 71 RawObject* raw_obj = RawObject::FromAddr(page->object_start()); |
| 72 if (raw_obj->IsMarked()) { | 72 if (raw_obj->IsMarked()) { |
| 73 raw_obj->ClearMarkBit(); | 73 raw_obj->ClearMarkBit(); |
| 74 words_to_end = (raw_obj->Size() >> kWordSizeLog2); | 74 words_to_end = (raw_obj->Size(class_table_) >> kWordSizeLog2); |
| 75 } | 75 } |
| 76 #ifdef DEBUG | 76 #ifdef DEBUG |
| 77 // String::MakeExternal and Array::MakeArray create trailing filler objects, | 77 // String::MakeExternal and Array::MakeArray create trailing filler objects, |
| 78 // but they are always unreachable. Verify that they are not marked. | 78 // but they are always unreachable. Verify that they are not marked. |
| 79 uword current = RawObject::ToAddr(raw_obj) + raw_obj->Size(); | 79 uword current = RawObject::ToAddr(raw_obj) + raw_obj->Size(class_table_); |
| 80 uword end = page->object_end(); | 80 uword end = page->object_end(); |
| 81 while (current < end) { | 81 while (current < end) { |
| 82 RawObject* cur_obj = RawObject::FromAddr(current); | 82 RawObject* cur_obj = RawObject::FromAddr(current); |
| 83 ASSERT(!cur_obj->IsMarked()); | 83 ASSERT(!cur_obj->IsMarked()); |
| 84 intptr_t obj_size = cur_obj->Size(); | 84 intptr_t obj_size = cur_obj->Size(class_table_); |
| 85 memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size); | 85 memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size); |
| 86 current += obj_size; | 86 current += obj_size; |
| 87 } | 87 } |
| 88 #endif // DEBUG | 88 #endif // DEBUG |
| 89 return words_to_end; | 89 return words_to_end; |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 class SweeperTask : public ThreadPool::Task { | 93 class SweeperTask : public ThreadPool::Task { |
| 94 public: | 94 public: |
| 95 SweeperTask(Isolate* isolate, | 95 SweeperTask(ClassTable* class_table, |
| 96 PageSpace* old_space, | 96 PageSpace* old_space, |
| 97 HeapPage* first, | 97 HeapPage* first, |
| 98 HeapPage* last, | 98 HeapPage* last, |
| 99 FreeList* freelist) | 99 FreeList* freelist) |
| 100 : task_isolate_(isolate), | 100 : class_table_(class_table), |
| 101 old_space_(old_space), | 101 old_space_(old_space), |
| 102 first_(first), | 102 first_(first), |
| 103 last_(last), | 103 last_(last), |
| 104 freelist_(freelist) { | 104 freelist_(freelist) { |
| 105 ASSERT(task_isolate_ != NULL); | 105 ASSERT(class_table_ != NULL); |
| 106 ASSERT(first_ != NULL); | 106 ASSERT(first_ != NULL); |
| 107 ASSERT(old_space_ != NULL); | 107 ASSERT(old_space_ != NULL); |
| 108 ASSERT(last_ != NULL); | 108 ASSERT(last_ != NULL); |
| 109 ASSERT(freelist_ != NULL); | 109 ASSERT(freelist_ != NULL); |
| 110 MonitorLocker ml(old_space_->tasks_lock()); | 110 MonitorLocker ml(old_space_->tasks_lock()); |
| 111 old_space_->set_tasks(old_space_->tasks() + 1); | 111 old_space_->set_tasks(old_space_->tasks() + 1); |
| 112 ml.Notify(); | 112 ml.Notify(); |
| 113 } | 113 } |
| 114 | 114 |
| 115 virtual void Run() { | 115 virtual void Run() { |
| 116 Isolate::SetCurrent(task_isolate_); | 116 GCSweeper sweeper(class_table_); |
| 117 GCSweeper sweeper; | |
| 118 | 117 |
| 119 HeapPage* page = first_; | 118 HeapPage* page = first_; |
| 120 HeapPage* prev_page = NULL; | 119 HeapPage* prev_page = NULL; |
| 121 | 120 |
| 122 while (page != NULL) { | 121 while (page != NULL) { |
| 123 HeapPage* next_page = page->next(); | 122 HeapPage* next_page = page->next(); |
| 124 ASSERT(page->type() == HeapPage::kData); | 123 ASSERT(page->type() == HeapPage::kData); |
| 125 bool page_in_use = sweeper.SweepPage(page, freelist_, false); | 124 bool page_in_use = sweeper.SweepPage(page, freelist_, false); |
| 126 if (page_in_use) { | 125 if (page_in_use) { |
| 127 prev_page = page; | 126 prev_page = page; |
| 128 } else { | 127 } else { |
| 129 old_space_->FreePage(page, prev_page); | 128 old_space_->FreePage(page, prev_page); |
| 130 } | 129 } |
| 131 { | 130 { |
| 132 // Notify the mutator thread that we have added elements to the free | 131 // Notify the mutator thread that we have added elements to the free |
| 133 // list or that more capacity is available. | 132 // list or that more capacity is available. |
| 134 MonitorLocker ml(old_space_->tasks_lock()); | 133 MonitorLocker ml(old_space_->tasks_lock()); |
| 135 ml.Notify(); | 134 ml.Notify(); |
| 136 } | 135 } |
| 137 if (page == last_) break; | 136 if (page == last_) break; |
| 138 page = next_page; | 137 page = next_page; |
| 139 } | 138 } |
| 140 // This sweeper task is done. Notify the original isolate. | 139 // This sweeper task is done. Notify the original isolate. |
| 141 { | 140 { |
| 142 MonitorLocker ml(old_space_->tasks_lock()); | 141 MonitorLocker ml(old_space_->tasks_lock()); |
| 143 old_space_->set_tasks(old_space_->tasks() - 1); | 142 old_space_->set_tasks(old_space_->tasks() - 1); |
| 144 ml.Notify(); | 143 ml.Notify(); |
| 145 } | 144 } |
| 146 Isolate::SetCurrent(NULL); | |
| 147 delete task_isolate_; | |
| 148 } | 145 } |
| 149 | 146 |
| 150 private: | 147 private: |
| 151 Isolate* task_isolate_; | 148 ClassTable* class_table_; |
| 152 PageSpace* old_space_; | 149 PageSpace* old_space_; |
| 153 HeapPage* first_; | 150 HeapPage* first_; |
| 154 HeapPage* last_; | 151 HeapPage* last_; |
| 155 FreeList* freelist_; | 152 FreeList* freelist_; |
| 156 }; | 153 }; |
| 157 | 154 |
| 158 | 155 |
| 159 void GCSweeper::SweepConcurrent(Isolate* isolate, | 156 void GCSweeper::SweepConcurrent(Isolate* isolate, |
| 160 HeapPage* first, | 157 HeapPage* first, |
| 161 HeapPage* last, | 158 HeapPage* last, |
| 162 FreeList* freelist) { | 159 FreeList* freelist) { |
| 163 SweeperTask* task = | 160 SweeperTask* task = |
| 164 new SweeperTask(isolate->ShallowCopy(), | 161 new SweeperTask(isolate->class_table(), |
| 165 isolate->heap()->old_space(), | 162 isolate->heap()->old_space(), |
| 166 first, last, | 163 first, last, |
| 167 freelist); | 164 freelist); |
| 168 ThreadPool* pool = Dart::thread_pool(); | 165 ThreadPool* pool = Dart::thread_pool(); |
| 169 pool->Run(task); | 166 pool->Run(task); |
| 170 } | 167 } |
| 171 | 168 |
| 172 } // namespace dart | 169 } // namespace dart |
| OLD | NEW |