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/pages.h" | 5 #include "vm/pages.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/compiler_stats.h" | 8 #include "vm/compiler_stats.h" |
| 9 #include "vm/gc_marker.h" | 9 #include "vm/gc_marker.h" |
| 10 #include "vm/gc_sweeper.h" | 10 #include "vm/gc_sweeper.h" |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 if ((growth_policy == kForceGrowth || | 337 if ((growth_policy == kForceGrowth || |
| 338 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && | 338 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && |
| 339 CanIncreaseCapacityInWords(kPageSizeInWords)) { | 339 CanIncreaseCapacityInWords(kPageSizeInWords)) { |
| 340 HeapPage* page = AllocatePage(type); | 340 HeapPage* page = AllocatePage(type); |
| 341 if (page == NULL) { | 341 if (page == NULL) { |
| 342 return 0; | 342 return 0; |
| 343 } | 343 } |
| 344 // Start of the newly allocated page is the allocated object. | 344 // Start of the newly allocated page is the allocated object. |
| 345 result = page->object_start(); | 345 result = page->object_start(); |
| 346 // Note: usage_.capacity_in_words is increased by AllocatePage. | 346 // Note: usage_.capacity_in_words is increased by AllocatePage. |
| 347 usage_.used_in_words += size >> kWordSizeLog2; | 347 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
| 348 (size >> kWordSizeLog2)); | |
| 348 // Enqueue the remainder in the free list. | 349 // Enqueue the remainder in the free list. |
| 349 uword free_start = result + size; | 350 uword free_start = result + size; |
| 350 intptr_t free_size = page->object_end() - free_start; | 351 intptr_t free_size = page->object_end() - free_start; |
| 351 if (free_size > 0) { | 352 if (free_size > 0) { |
| 352 if (is_locked) { | 353 if (is_locked) { |
| 353 freelist_[type].FreeLocked(free_start, free_size); | 354 freelist_[type].FreeLocked(free_start, free_size); |
| 354 } else { | 355 } else { |
| 355 freelist_[type].Free(free_start, free_size); | 356 freelist_[type].Free(free_start, free_size); |
| 356 } | 357 } |
| 357 } | 358 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 374 if (size < kAllocatablePageSize) { | 375 if (size < kAllocatablePageSize) { |
| 375 if (is_locked) { | 376 if (is_locked) { |
| 376 result = freelist_[type].TryAllocateLocked(size, is_protected); | 377 result = freelist_[type].TryAllocateLocked(size, is_protected); |
| 377 } else { | 378 } else { |
| 378 result = freelist_[type].TryAllocate(size, is_protected); | 379 result = freelist_[type].TryAllocate(size, is_protected); |
| 379 } | 380 } |
| 380 if (result == 0) { | 381 if (result == 0) { |
| 381 result = TryAllocateInFreshPage(size, type, growth_policy, is_locked); | 382 result = TryAllocateInFreshPage(size, type, growth_policy, is_locked); |
| 382 // usage_ is updated by the call above. | 383 // usage_ is updated by the call above. |
| 383 } else { | 384 } else { |
| 384 usage_.used_in_words += size >> kWordSizeLog2; | 385 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
|
Ivan Posva
2016/01/29 18:54:07
I am wondering whether we could make this a per th
siva
2016/01/29 20:52:17
Yes, we could do that, I will do it in a new CL.
| |
| 386 (size >> kWordSizeLog2)); | |
| 385 } | 387 } |
| 386 } else { | 388 } else { |
| 387 // Large page allocation. | 389 // Large page allocation. |
| 388 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); | 390 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); |
| 389 if ((page_size_in_words << kWordSizeLog2) < size) { | 391 if ((page_size_in_words << kWordSizeLog2) < size) { |
| 390 // On overflow we fail to allocate. | 392 // On overflow we fail to allocate. |
| 391 return 0; | 393 return 0; |
| 392 } | 394 } |
| 393 SpaceUsage after_allocation = GetCurrentUsage(); | 395 SpaceUsage after_allocation = GetCurrentUsage(); |
| 394 after_allocation.used_in_words += size >> kWordSizeLog2; | 396 after_allocation.used_in_words += size >> kWordSizeLog2; |
| 395 after_allocation.capacity_in_words += page_size_in_words; | 397 after_allocation.capacity_in_words += page_size_in_words; |
| 396 if ((growth_policy == kForceGrowth || | 398 if ((growth_policy == kForceGrowth || |
| 397 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && | 399 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && |
| 398 CanIncreaseCapacityInWords(page_size_in_words)) { | 400 CanIncreaseCapacityInWords(page_size_in_words)) { |
| 399 HeapPage* page = AllocateLargePage(size, type); | 401 HeapPage* page = AllocateLargePage(size, type); |
| 400 if (page != NULL) { | 402 if (page != NULL) { |
| 401 result = page->object_start(); | 403 result = page->object_start(); |
| 402 // Note: usage_.capacity_in_words is increased by AllocateLargePage. | 404 // Note: usage_.capacity_in_words is increased by AllocateLargePage. |
| 403 usage_.used_in_words += size >> kWordSizeLog2; | 405 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
| 406 (size >> kWordSizeLog2)); | |
| 404 } | 407 } |
| 405 } | 408 } |
| 406 } | 409 } |
| 410 #ifdef DEBUG | |
| 407 if (result != 0) { | 411 if (result != 0) { |
| 408 #ifdef DEBUG | |
| 409 // A successful allocation should increase usage_. | 412 // A successful allocation should increase usage_. |
| 410 ASSERT(usage_before.used_in_words < usage_.used_in_words); | 413 ASSERT(usage_before.used_in_words < usage_.used_in_words); |
| 414 } | |
| 415 // Note we cannot assert that a failed allocation should not change | |
| 416 // used_in_words as another thread could have changed used_in_words. | |
| 411 #endif | 417 #endif |
| 412 } else { | |
| 413 #ifdef DEBUG | |
| 414 // A failed allocation should not change used_in_words. | |
| 415 ASSERT(usage_before.used_in_words == usage_.used_in_words); | |
| 416 #endif | |
| 417 } | |
| 418 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); | 418 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); |
| 419 return result; | 419 return result; |
| 420 } | 420 } |
| 421 | 421 |
| 422 | 422 |
| 423 void PageSpace::AcquireDataLock() { | 423 void PageSpace::AcquireDataLock() { |
| 424 freelist_[HeapPage::kData].mutex()->Lock(); | 424 freelist_[HeapPage::kData].mutex()->Lock(); |
| 425 } | 425 } |
| 426 | 426 |
| 427 | 427 |
| 428 void PageSpace::ReleaseDataLock() { | 428 void PageSpace::ReleaseDataLock() { |
| 429 freelist_[HeapPage::kData].mutex()->Unlock(); | 429 freelist_[HeapPage::kData].mutex()->Unlock(); |
| 430 } | 430 } |
| 431 | 431 |
| 432 | 432 |
| 433 void PageSpace::AllocateExternal(intptr_t size) { | 433 void PageSpace::AllocateExternal(intptr_t size) { |
| 434 intptr_t size_in_words = size >> kWordSizeLog2; | 434 intptr_t size_in_words = size >> kWordSizeLog2; |
| 435 usage_.external_in_words += size_in_words; | 435 AtomicOperations::FetchAndIncrementBy(&(usage_.external_in_words), |
| 436 size_in_words); | |
| 436 // TODO(koda): Control growth. | 437 // TODO(koda): Control growth. |
| 437 } | 438 } |
| 438 | 439 |
| 439 | 440 |
| 440 void PageSpace::FreeExternal(intptr_t size) { | 441 void PageSpace::FreeExternal(intptr_t size) { |
| 441 intptr_t size_in_words = size >> kWordSizeLog2; | 442 intptr_t size_in_words = size >> kWordSizeLog2; |
| 442 usage_.external_in_words -= size_in_words; | 443 AtomicOperations::FetchAndDecrementBy(&(usage_.external_in_words), |
| 444 size_in_words); | |
| 443 } | 445 } |
| 444 | 446 |
| 445 | 447 |
| 446 // Provides exclusive access to all pages, and ensures they are walkable. | 448 // Provides exclusive access to all pages, and ensures they are walkable. |
| 447 class ExclusivePageIterator : ValueObject { | 449 class ExclusivePageIterator : ValueObject { |
| 448 public: | 450 public: |
| 449 explicit ExclusivePageIterator(const PageSpace* space) | 451 explicit ExclusivePageIterator(const PageSpace* space) |
| 450 : space_(space), ml_(space->pages_lock_) { | 452 : space_(space), ml_(space->pages_lock_) { |
| 451 space_->MakeIterable(); | 453 space_->MakeIterable(); |
| 452 page_ = space_->pages_; | 454 page_ = space_->pages_; |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 832 // Make code pages writable. | 834 // Make code pages writable. |
| 833 WriteProtectCode(false); | 835 WriteProtectCode(false); |
| 834 | 836 |
| 835 // Save old value before GCMarker visits the weak persistent handles. | 837 // Save old value before GCMarker visits the weak persistent handles. |
| 836 SpaceUsage usage_before = GetCurrentUsage(); | 838 SpaceUsage usage_before = GetCurrentUsage(); |
| 837 | 839 |
| 838 // Mark all reachable old-gen objects. | 840 // Mark all reachable old-gen objects. |
| 839 bool collect_code = FLAG_collect_code && ShouldCollectCode(); | 841 bool collect_code = FLAG_collect_code && ShouldCollectCode(); |
| 840 GCMarker marker(heap_); | 842 GCMarker marker(heap_); |
| 841 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code); | 843 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code); |
| 842 usage_.used_in_words = marker.marked_words(); | 844 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
| 845 marker.marked_words()); | |
| 843 | 846 |
| 844 int64_t mid1 = OS::GetCurrentTimeMicros(); | 847 int64_t mid1 = OS::GetCurrentTimeMicros(); |
| 845 | 848 |
| 846 // Abandon the remainder of the bump allocation block. | 849 // Abandon the remainder of the bump allocation block. |
| 847 AbandonBumpAllocation(); | 850 AbandonBumpAllocation(); |
| 848 // Reset the freelists and setup sweeping. | 851 // Reset the freelists and setup sweeping. |
| 849 freelist_[HeapPage::kData].Reset(); | 852 freelist_[HeapPage::kData].Reset(); |
| 850 freelist_[HeapPage::kExecutable].Reset(); | 853 freelist_[HeapPage::kExecutable].Reset(); |
| 851 | 854 |
| 852 int64_t mid2 = OS::GetCurrentTimeMicros(); | 855 int64_t mid2 = OS::GetCurrentTimeMicros(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 998 freelist_[HeapPage::kData].Free(bump_top_, remaining); | 1001 freelist_[HeapPage::kData].Free(bump_top_, remaining); |
| 999 } | 1002 } |
| 1000 } | 1003 } |
| 1001 bump_top_ = reinterpret_cast<uword>(block); | 1004 bump_top_ = reinterpret_cast<uword>(block); |
| 1002 bump_end_ = bump_top_ + block_size; | 1005 bump_end_ = bump_top_ + block_size; |
| 1003 remaining = block_size; | 1006 remaining = block_size; |
| 1004 } | 1007 } |
| 1005 ASSERT(remaining >= size); | 1008 ASSERT(remaining >= size); |
| 1006 uword result = bump_top_; | 1009 uword result = bump_top_; |
| 1007 bump_top_ += size; | 1010 bump_top_ += size; |
| 1008 usage_.used_in_words += size >> kWordSizeLog2; | 1011 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
| 1012 (size >> kWordSizeLog2)); | |
| 1009 // Note: Remaining block is unwalkable until MakeIterable is called. | 1013 // Note: Remaining block is unwalkable until MakeIterable is called. |
| 1010 #ifdef DEBUG | 1014 #ifdef DEBUG |
| 1011 if (bump_top_ < bump_end_) { | 1015 if (bump_top_ < bump_end_) { |
| 1012 // Fail fast if we try to walk the remaining block. | 1016 // Fail fast if we try to walk the remaining block. |
| 1013 COMPILE_ASSERT(kIllegalCid == 0); | 1017 COMPILE_ASSERT(kIllegalCid == 0); |
| 1014 *reinterpret_cast<uword*>(bump_top_) = 0; | 1018 *reinterpret_cast<uword*>(bump_top_) = 0; |
| 1015 } | 1019 } |
| 1016 #endif // DEBUG | 1020 #endif // DEBUG |
| 1017 return result; | 1021 return result; |
| 1018 } | 1022 } |
| 1019 | 1023 |
| 1020 | 1024 |
| 1021 uword PageSpace::TryAllocateDataBump(intptr_t size, | 1025 uword PageSpace::TryAllocateDataBump(intptr_t size, |
| 1022 GrowthPolicy growth_policy) { | 1026 GrowthPolicy growth_policy) { |
| 1023 return TryAllocateDataBumpInternal(size, growth_policy, false); | 1027 return TryAllocateDataBumpInternal(size, growth_policy, false); |
| 1024 } | 1028 } |
| 1025 | 1029 |
| 1026 | 1030 |
| 1027 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size, | 1031 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size, |
| 1028 GrowthPolicy growth_policy) { | 1032 GrowthPolicy growth_policy) { |
| 1029 return TryAllocateDataBumpInternal(size, growth_policy, true); | 1033 return TryAllocateDataBumpInternal(size, growth_policy, true); |
| 1030 } | 1034 } |
| 1031 | 1035 |
| 1032 | 1036 |
| 1033 uword PageSpace::TryAllocatePromoLocked(intptr_t size, | 1037 uword PageSpace::TryAllocatePromoLocked(intptr_t size, |
| 1034 GrowthPolicy growth_policy) { | 1038 GrowthPolicy growth_policy) { |
| 1035 FreeList* freelist = &freelist_[HeapPage::kData]; | 1039 FreeList* freelist = &freelist_[HeapPage::kData]; |
| 1036 uword result = freelist->TryAllocateSmallLocked(size); | 1040 uword result = freelist->TryAllocateSmallLocked(size); |
| 1037 if (result != 0) { | 1041 if (result != 0) { |
| 1038 usage_.used_in_words += size >> kWordSizeLog2; | 1042 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), |
| 1043 (size >> kWordSizeLog2)); | |
| 1039 return result; | 1044 return result; |
| 1040 } | 1045 } |
| 1041 result = TryAllocateDataBumpLocked(size, growth_policy); | 1046 result = TryAllocateDataBumpLocked(size, growth_policy); |
| 1042 if (result != 0) return result; | 1047 if (result != 0) return result; |
| 1043 return TryAllocateDataLocked(size, growth_policy); | 1048 return TryAllocateDataLocked(size, growth_policy); |
| 1044 } | 1049 } |
| 1045 | 1050 |
| 1046 | 1051 |
| 1047 uword PageSpace::TryAllocateSmiInitializedLocked(intptr_t size, | 1052 uword PageSpace::TryAllocateSmiInitializedLocked(intptr_t size, |
| 1048 GrowthPolicy growth_policy) { | 1053 GrowthPolicy growth_policy) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1215 return 0; | 1220 return 0; |
| 1216 } else { | 1221 } else { |
| 1217 ASSERT(total_time >= gc_time); | 1222 ASSERT(total_time >= gc_time); |
| 1218 int result = static_cast<int>((static_cast<double>(gc_time) / | 1223 int result = static_cast<int>((static_cast<double>(gc_time) / |
| 1219 static_cast<double>(total_time)) * 100); | 1224 static_cast<double>(total_time)) * 100); |
| 1220 return result; | 1225 return result; |
| 1221 } | 1226 } |
| 1222 } | 1227 } |
| 1223 | 1228 |
| 1224 } // namespace dart | 1229 } // namespace dart |
| OLD | NEW |