| 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/pages.h" | 5 #include "vm/pages.h" |
| 6 | 6 |
| 7 #include "platform/address_sanitizer.h" | 7 #include "platform/address_sanitizer.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/compiler_stats.h" | 9 #include "vm/compiler_stats.h" |
| 10 #include "vm/gc_marker.h" | 10 #include "vm/gc_marker.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 HeapPage* result = Initialize(memory, type); | 86 HeapPage* result = Initialize(memory, type); |
| 87 if (result == NULL) { | 87 if (result == NULL) { |
| 88 delete memory; // Release reservation to OS. | 88 delete memory; // Release reservation to OS. |
| 89 return NULL; | 89 return NULL; |
| 90 } | 90 } |
| 91 return result; | 91 return result; |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 void HeapPage::Deallocate() { | 95 void HeapPage::Deallocate() { |
| 96 bool is_embedder_allocated = embedder_allocated(); | 96 bool image_page = is_image_page(); |
| 97 | 97 |
| 98 if (!is_embedder_allocated) { | 98 if (!image_page) { |
| 99 LSAN_UNREGISTER_ROOT_REGION(this, sizeof(*this)); | 99 LSAN_UNREGISTER_ROOT_REGION(this, sizeof(*this)); |
| 100 } | 100 } |
| 101 | 101 |
| 102 // For a regular heap pages, the memory for this object will become | 102 // For a regular heap pages, the memory for this object will become |
| 103 // unavailable after the delete below. | 103 // unavailable after the delete below. |
| 104 delete memory_; | 104 delete memory_; |
| 105 | 105 |
| 106 // For a heap page from a snapshot, the HeapPage object lives in the malloc | 106 // For a heap page from a snapshot, the HeapPage object lives in the malloc |
| 107 // heap rather than the page itself. | 107 // heap rather than the page itself. |
| 108 if (is_embedder_allocated) { | 108 if (image_page) { |
| 109 free(this); | 109 free(this); |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 | 112 |
| 113 | 113 |
| 114 void HeapPage::VisitObjects(ObjectVisitor* visitor) const { | 114 void HeapPage::VisitObjects(ObjectVisitor* visitor) const { |
| 115 NoSafepointScope no_safepoint; | 115 NoSafepointScope no_safepoint; |
| 116 uword obj_addr = object_start(); | 116 uword obj_addr = object_start(); |
| 117 uword end_addr = object_end(); | 117 uword end_addr = object_end(); |
| 118 while (obj_addr < end_addr) { | 118 while (obj_addr < end_addr) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 149 } | 149 } |
| 150 obj_addr = next_obj_addr; | 150 obj_addr = next_obj_addr; |
| 151 } | 151 } |
| 152 ASSERT(obj_addr == end_addr); | 152 ASSERT(obj_addr == end_addr); |
| 153 } | 153 } |
| 154 return Object::null(); | 154 return Object::null(); |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| 158 void HeapPage::WriteProtect(bool read_only) { | 158 void HeapPage::WriteProtect(bool read_only) { |
| 159 ASSERT(!embedder_allocated()); | 159 ASSERT(!is_image_page()); |
| 160 | 160 |
| 161 VirtualMemory::Protection prot; | 161 VirtualMemory::Protection prot; |
| 162 if (read_only) { | 162 if (read_only) { |
| 163 if (type_ == kExecutable) { | 163 if (type_ == kExecutable) { |
| 164 prot = VirtualMemory::kReadExecute; | 164 prot = VirtualMemory::kReadExecute; |
| 165 } else { | 165 } else { |
| 166 prot = VirtualMemory::kReadOnly; | 166 prot = VirtualMemory::kReadOnly; |
| 167 } | 167 } |
| 168 } else { | 168 } else { |
| 169 prot = VirtualMemory::kReadWrite; | 169 prot = VirtualMemory::kReadWrite; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } | 244 } |
| 245 pages_tail_ = page; | 245 pages_tail_ = page; |
| 246 } else { | 246 } else { |
| 247 // Should not allocate executable pages when running from a precompiled | 247 // Should not allocate executable pages when running from a precompiled |
| 248 // snapshot. | 248 // snapshot. |
| 249 ASSERT(Dart::vm_snapshot_kind() != Snapshot::kAppAOT); | 249 ASSERT(Dart::vm_snapshot_kind() != Snapshot::kAppAOT); |
| 250 | 250 |
| 251 if (exec_pages_ == NULL) { | 251 if (exec_pages_ == NULL) { |
| 252 exec_pages_ = page; | 252 exec_pages_ = page; |
| 253 } else { | 253 } else { |
| 254 if (FLAG_write_protect_code && !exec_pages_tail_->embedder_allocated()) { | 254 if (FLAG_write_protect_code && !exec_pages_tail_->is_image_page()) { |
| 255 exec_pages_tail_->WriteProtect(false); | 255 exec_pages_tail_->WriteProtect(false); |
| 256 } | 256 } |
| 257 exec_pages_tail_->set_next(page); | 257 exec_pages_tail_->set_next(page); |
| 258 if (FLAG_write_protect_code && !exec_pages_tail_->embedder_allocated()) { | 258 if (FLAG_write_protect_code && !exec_pages_tail_->is_image_page()) { |
| 259 exec_pages_tail_->WriteProtect(true); | 259 exec_pages_tail_->WriteProtect(true); |
| 260 } | 260 } |
| 261 } | 261 } |
| 262 exec_pages_tail_ = page; | 262 exec_pages_tail_ = page; |
| 263 } | 263 } |
| 264 IncreaseCapacityInWordsLocked(kPageSizeInWords); | 264 IncreaseCapacityInWordsLocked(kPageSizeInWords); |
| 265 page->set_object_end(page->memory_->end()); | 265 page->set_object_end(page->memory_->end()); |
| 266 return page; | 266 return page; |
| 267 } | 267 } |
| 268 | 268 |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 } | 636 } |
| 637 | 637 |
| 638 | 638 |
| 639 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { | 639 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { |
| 640 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 640 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 641 it.page()->VisitObjects(visitor); | 641 it.page()->VisitObjects(visitor); |
| 642 } | 642 } |
| 643 } | 643 } |
| 644 | 644 |
| 645 | 645 |
| 646 void PageSpace::VisitObjectsNoExternalPages(ObjectVisitor* visitor) const { | 646 void PageSpace::VisitObjectsNoImagePages(ObjectVisitor* visitor) const { |
| 647 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 647 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 648 if (!it.page()->embedder_allocated()) { | 648 if (!it.page()->is_image_page()) { |
| 649 it.page()->VisitObjects(visitor); | 649 it.page()->VisitObjects(visitor); |
| 650 } | 650 } |
| 651 } | 651 } |
| 652 } | 652 } |
| 653 | 653 |
| 654 | 654 |
| 655 void PageSpace::VisitObjectsExternalPages(ObjectVisitor* visitor) const { | 655 void PageSpace::VisitObjectsImagePages(ObjectVisitor* visitor) const { |
| 656 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 656 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 657 if (it.page()->embedder_allocated()) { | 657 if (it.page()->is_image_page()) { |
| 658 it.page()->VisitObjects(visitor); | 658 it.page()->VisitObjects(visitor); |
| 659 } | 659 } |
| 660 } | 660 } |
| 661 } | 661 } |
| 662 | 662 |
| 663 | 663 |
| 664 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 664 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 665 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 665 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 666 it.page()->VisitObjectPointers(visitor); | 666 it.page()->VisitObjectPointers(visitor); |
| 667 } | 667 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 return Object::null(); | 701 return Object::null(); |
| 702 } | 702 } |
| 703 | 703 |
| 704 | 704 |
| 705 void PageSpace::WriteProtect(bool read_only) { | 705 void PageSpace::WriteProtect(bool read_only) { |
| 706 if (read_only) { | 706 if (read_only) { |
| 707 // Avoid MakeIterable trying to write to the heap. | 707 // Avoid MakeIterable trying to write to the heap. |
| 708 AbandonBumpAllocation(); | 708 AbandonBumpAllocation(); |
| 709 } | 709 } |
| 710 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 710 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 711 if (!it.page()->embedder_allocated()) { | 711 if (!it.page()->is_image_page()) { |
| 712 it.page()->WriteProtect(read_only); | 712 it.page()->WriteProtect(read_only); |
| 713 } | 713 } |
| 714 } | 714 } |
| 715 } | 715 } |
| 716 | 716 |
| 717 | 717 |
| 718 #ifndef PRODUCT | 718 #ifndef PRODUCT |
| 719 void PageSpace::PrintToJSONObject(JSONObject* object) const { | 719 void PageSpace::PrintToJSONObject(JSONObject* object) const { |
| 720 if (!FLAG_support_service) { | 720 if (!FLAG_support_service) { |
| 721 return; | 721 return; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 | 821 |
| 822 | 822 |
| 823 void PageSpace::WriteProtectCode(bool read_only) { | 823 void PageSpace::WriteProtectCode(bool read_only) { |
| 824 if (FLAG_write_protect_code) { | 824 if (FLAG_write_protect_code) { |
| 825 MutexLocker ml(pages_lock_); | 825 MutexLocker ml(pages_lock_); |
| 826 NoSafepointScope no_safepoint; | 826 NoSafepointScope no_safepoint; |
| 827 // No need to go through all of the data pages first. | 827 // No need to go through all of the data pages first. |
| 828 HeapPage* page = exec_pages_; | 828 HeapPage* page = exec_pages_; |
| 829 while (page != NULL) { | 829 while (page != NULL) { |
| 830 ASSERT(page->type() == HeapPage::kExecutable); | 830 ASSERT(page->type() == HeapPage::kExecutable); |
| 831 if (!page->embedder_allocated()) { | 831 if (!page->is_image_page()) { |
| 832 page->WriteProtect(read_only); | 832 page->WriteProtect(read_only); |
| 833 } | 833 } |
| 834 page = page->next(); | 834 page = page->next(); |
| 835 } | 835 } |
| 836 page = large_pages_; | 836 page = large_pages_; |
| 837 while (page != NULL) { | 837 while (page != NULL) { |
| 838 if (page->type() == HeapPage::kExecutable && | 838 if (page->type() == HeapPage::kExecutable && !page->is_image_page()) { |
| 839 !page->embedder_allocated()) { | |
| 840 page->WriteProtect(read_only); | 839 page->WriteProtect(read_only); |
| 841 } | 840 } |
| 842 page = page->next(); | 841 page = page->next(); |
| 843 } | 842 } |
| 844 } | 843 } |
| 845 } | 844 } |
| 846 | 845 |
| 847 | 846 |
| 848 void PageSpace::MarkSweep(bool invoke_api_callbacks) { | 847 void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
| 849 Thread* thread = Thread::Current(); | 848 Thread* thread = Thread::Current(); |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 AtomicOperations::IncrementBy(&(usage_.used_in_words), | 1090 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 1092 (size >> kWordSizeLog2)); | 1091 (size >> kWordSizeLog2)); |
| 1093 return result; | 1092 return result; |
| 1094 } | 1093 } |
| 1095 result = TryAllocateDataBumpLocked(size, growth_policy); | 1094 result = TryAllocateDataBumpLocked(size, growth_policy); |
| 1096 if (result != 0) return result; | 1095 if (result != 0) return result; |
| 1097 return TryAllocateDataLocked(size, growth_policy); | 1096 return TryAllocateDataLocked(size, growth_policy); |
| 1098 } | 1097 } |
| 1099 | 1098 |
| 1100 | 1099 |
| 1101 void PageSpace::SetupExternalPage(void* pointer, | 1100 void PageSpace::SetupImagePage(void* pointer, uword size, bool is_executable) { |
| 1102 uword size, | |
| 1103 bool is_executable) { | |
| 1104 // Setup a HeapPage so precompiled Instructions can be traversed. | 1101 // Setup a HeapPage so precompiled Instructions can be traversed. |
| 1105 // Instructions are contiguous at [pointer, pointer + size). HeapPage | 1102 // Instructions are contiguous at [pointer, pointer + size). HeapPage |
| 1106 // expects to find objects at [memory->start() + ObjectStartOffset, | 1103 // expects to find objects at [memory->start() + ObjectStartOffset, |
| 1107 // memory->end()). | 1104 // memory->end()). |
| 1108 uword offset = HeapPage::ObjectStartOffset(); | 1105 uword offset = HeapPage::ObjectStartOffset(); |
| 1109 pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset); | 1106 pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset); |
| 1110 size += offset; | 1107 size += offset; |
| 1111 | 1108 |
| 1112 VirtualMemory* memory = VirtualMemory::ForExternalPage(pointer, size); | 1109 VirtualMemory* memory = VirtualMemory::ForImagePage(pointer, size); |
| 1113 ASSERT(memory != NULL); | 1110 ASSERT(memory != NULL); |
| 1114 HeapPage* page = reinterpret_cast<HeapPage*>(malloc(sizeof(HeapPage))); | 1111 HeapPage* page = reinterpret_cast<HeapPage*>(malloc(sizeof(HeapPage))); |
| 1115 page->memory_ = memory; | 1112 page->memory_ = memory; |
| 1116 page->next_ = NULL; | 1113 page->next_ = NULL; |
| 1117 page->object_end_ = memory->end(); | 1114 page->object_end_ = memory->end(); |
| 1118 | 1115 |
| 1119 MutexLocker ml(pages_lock_); | 1116 MutexLocker ml(pages_lock_); |
| 1120 HeapPage **first, **tail; | 1117 HeapPage **first, **tail; |
| 1121 if (is_executable) { | 1118 if (is_executable) { |
| 1122 ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment())); | 1119 ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment())); |
| 1123 page->type_ = HeapPage::kExecutable; | 1120 page->type_ = HeapPage::kExecutable; |
| 1124 first = &exec_pages_; | 1121 first = &exec_pages_; |
| 1125 tail = &exec_pages_tail_; | 1122 tail = &exec_pages_tail_; |
| 1126 } else { | 1123 } else { |
| 1127 page->type_ = HeapPage::kData; | 1124 page->type_ = HeapPage::kData; |
| 1128 first = &pages_; | 1125 first = &pages_; |
| 1129 tail = &pages_tail_; | 1126 tail = &pages_tail_; |
| 1130 } | 1127 } |
| 1131 if (*first == NULL) { | 1128 if (*first == NULL) { |
| 1132 *first = page; | 1129 *first = page; |
| 1133 } else { | 1130 } else { |
| 1134 if (is_executable && FLAG_write_protect_code && | 1131 if (is_executable && FLAG_write_protect_code && !(*tail)->is_image_page()) { |
| 1135 !(*tail)->embedder_allocated()) { | |
| 1136 (*tail)->WriteProtect(false); | 1132 (*tail)->WriteProtect(false); |
| 1137 } | 1133 } |
| 1138 (*tail)->set_next(page); | 1134 (*tail)->set_next(page); |
| 1139 if (is_executable && FLAG_write_protect_code && | 1135 if (is_executable && FLAG_write_protect_code && !(*tail)->is_image_page()) { |
| 1140 !(*tail)->embedder_allocated()) { | |
| 1141 (*tail)->WriteProtect(true); | 1136 (*tail)->WriteProtect(true); |
| 1142 } | 1137 } |
| 1143 } | 1138 } |
| 1144 (*tail) = page; | 1139 (*tail) = page; |
| 1145 } | 1140 } |
| 1146 | 1141 |
| 1147 | 1142 |
| 1148 PageSpaceController::PageSpaceController(Heap* heap, | 1143 PageSpaceController::PageSpaceController(Heap* heap, |
| 1149 int heap_growth_ratio, | 1144 int heap_growth_ratio, |
| 1150 int heap_growth_max, | 1145 int heap_growth_max, |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 return 0; | 1295 return 0; |
| 1301 } else { | 1296 } else { |
| 1302 ASSERT(total_time >= gc_time); | 1297 ASSERT(total_time >= gc_time); |
| 1303 int result = static_cast<int>( | 1298 int result = static_cast<int>( |
| 1304 (static_cast<double>(gc_time) / static_cast<double>(total_time)) * 100); | 1299 (static_cast<double>(gc_time) / static_cast<double>(total_time)) * 100); |
| 1305 return result; | 1300 return result; |
| 1306 } | 1301 } |
| 1307 } | 1302 } |
| 1308 | 1303 |
| 1309 } // namespace dart | 1304 } // namespace dart |
| OLD | NEW |