| 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 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 if ((growth_policy == kForceGrowth || | 339 if ((growth_policy == kForceGrowth || |
| 340 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && | 340 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && |
| 341 CanIncreaseCapacityInWords(kPageSizeInWords)) { | 341 CanIncreaseCapacityInWords(kPageSizeInWords)) { |
| 342 HeapPage* page = AllocatePage(type); | 342 HeapPage* page = AllocatePage(type); |
| 343 if (page == NULL) { | 343 if (page == NULL) { |
| 344 return 0; | 344 return 0; |
| 345 } | 345 } |
| 346 // Start of the newly allocated page is the allocated object. | 346 // Start of the newly allocated page is the allocated object. |
| 347 result = page->object_start(); | 347 result = page->object_start(); |
| 348 // Note: usage_.capacity_in_words is increased by AllocatePage. | 348 // Note: usage_.capacity_in_words is increased by AllocatePage. |
| 349 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), | 349 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 350 (size >> kWordSizeLog2)); | 350 (size >> kWordSizeLog2)); |
| 351 // Enqueue the remainder in the free list. | 351 // Enqueue the remainder in the free list. |
| 352 uword free_start = result + size; | 352 uword free_start = result + size; |
| 353 intptr_t free_size = page->object_end() - free_start; | 353 intptr_t free_size = page->object_end() - free_start; |
| 354 if (free_size > 0) { | 354 if (free_size > 0) { |
| 355 if (is_locked) { | 355 if (is_locked) { |
| 356 freelist_[type].FreeLocked(free_start, free_size); | 356 freelist_[type].FreeLocked(free_start, free_size); |
| 357 } else { | 357 } else { |
| 358 freelist_[type].Free(free_start, free_size); | 358 freelist_[type].Free(free_start, free_size); |
| 359 } | 359 } |
| 360 } | 360 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 377 if (size < kAllocatablePageSize) { | 377 if (size < kAllocatablePageSize) { |
| 378 if (is_locked) { | 378 if (is_locked) { |
| 379 result = freelist_[type].TryAllocateLocked(size, is_protected); | 379 result = freelist_[type].TryAllocateLocked(size, is_protected); |
| 380 } else { | 380 } else { |
| 381 result = freelist_[type].TryAllocate(size, is_protected); | 381 result = freelist_[type].TryAllocate(size, is_protected); |
| 382 } | 382 } |
| 383 if (result == 0) { | 383 if (result == 0) { |
| 384 result = TryAllocateInFreshPage(size, type, growth_policy, is_locked); | 384 result = TryAllocateInFreshPage(size, type, growth_policy, is_locked); |
| 385 // usage_ is updated by the call above. | 385 // usage_ is updated by the call above. |
| 386 } else { | 386 } else { |
| 387 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), | 387 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 388 (size >> kWordSizeLog2)); | 388 (size >> kWordSizeLog2)); |
| 389 } | 389 } |
| 390 } else { | 390 } else { |
| 391 // Large page allocation. | 391 // Large page allocation. |
| 392 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); | 392 intptr_t page_size_in_words = LargePageSizeInWordsFor(size); |
| 393 if ((page_size_in_words << kWordSizeLog2) < size) { | 393 if ((page_size_in_words << kWordSizeLog2) < size) { |
| 394 // On overflow we fail to allocate. | 394 // On overflow we fail to allocate. |
| 395 return 0; | 395 return 0; |
| 396 } | 396 } |
| 397 SpaceUsage after_allocation = GetCurrentUsage(); | 397 SpaceUsage after_allocation = GetCurrentUsage(); |
| 398 after_allocation.used_in_words += size >> kWordSizeLog2; | 398 after_allocation.used_in_words += size >> kWordSizeLog2; |
| 399 after_allocation.capacity_in_words += page_size_in_words; | 399 after_allocation.capacity_in_words += page_size_in_words; |
| 400 if ((growth_policy == kForceGrowth || | 400 if ((growth_policy == kForceGrowth || |
| 401 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && | 401 !page_space_controller_.NeedsGarbageCollection(after_allocation)) && |
| 402 CanIncreaseCapacityInWords(page_size_in_words)) { | 402 CanIncreaseCapacityInWords(page_size_in_words)) { |
| 403 HeapPage* page = AllocateLargePage(size, type); | 403 HeapPage* page = AllocateLargePage(size, type); |
| 404 if (page != NULL) { | 404 if (page != NULL) { |
| 405 result = page->object_start(); | 405 result = page->object_start(); |
| 406 // Note: usage_.capacity_in_words is increased by AllocateLargePage. | 406 // Note: usage_.capacity_in_words is increased by AllocateLargePage. |
| 407 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), | 407 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 408 (size >> kWordSizeLog2)); | 408 (size >> kWordSizeLog2)); |
| 409 } | 409 } |
| 410 } | 410 } |
| 411 } | 411 } |
| 412 #ifdef DEBUG | 412 #ifdef DEBUG |
| 413 if (result != 0) { | 413 if (result != 0) { |
| 414 // A successful allocation should increase usage_. | 414 // A successful allocation should increase usage_. |
| 415 ASSERT(usage_before.used_in_words < usage_.used_in_words); | 415 ASSERT(usage_before.used_in_words < usage_.used_in_words); |
| 416 } | 416 } |
| 417 // Note we cannot assert that a failed allocation should not change | 417 // Note we cannot assert that a failed allocation should not change |
| 418 // used_in_words as another thread could have changed used_in_words. | 418 // used_in_words as another thread could have changed used_in_words. |
| 419 #endif | 419 #endif |
| 420 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); | 420 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); |
| 421 return result; | 421 return result; |
| 422 } | 422 } |
| 423 | 423 |
| 424 | 424 |
| 425 void PageSpace::AcquireDataLock() { | 425 void PageSpace::AcquireDataLock() { |
| 426 freelist_[HeapPage::kData].mutex()->Lock(); | 426 freelist_[HeapPage::kData].mutex()->Lock(); |
| 427 } | 427 } |
| 428 | 428 |
| 429 | 429 |
| 430 void PageSpace::ReleaseDataLock() { | 430 void PageSpace::ReleaseDataLock() { |
| 431 freelist_[HeapPage::kData].mutex()->Unlock(); | 431 freelist_[HeapPage::kData].mutex()->Unlock(); |
| 432 } | 432 } |
| 433 | 433 |
| 434 | 434 |
| 435 void PageSpace::AllocateExternal(intptr_t size) { | 435 void PageSpace::AllocateExternal(intptr_t size) { |
| 436 intptr_t size_in_words = size >> kWordSizeLog2; | 436 intptr_t size_in_words = size >> kWordSizeLog2; |
| 437 AtomicOperations::FetchAndIncrementBy(&(usage_.external_in_words), | 437 AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words); |
| 438 size_in_words); | |
| 439 // TODO(koda): Control growth. | 438 // TODO(koda): Control growth. |
| 440 } | 439 } |
| 441 | 440 |
| 442 | 441 |
| 443 void PageSpace::FreeExternal(intptr_t size) { | 442 void PageSpace::FreeExternal(intptr_t size) { |
| 444 intptr_t size_in_words = size >> kWordSizeLog2; | 443 intptr_t size_in_words = size >> kWordSizeLog2; |
| 445 AtomicOperations::FetchAndDecrementBy(&(usage_.external_in_words), | 444 AtomicOperations::DecrementBy(&(usage_.external_in_words), size_in_words); |
| 446 size_in_words); | |
| 447 } | 445 } |
| 448 | 446 |
| 449 | 447 |
| 450 // Provides exclusive access to all pages, and ensures they are walkable. | 448 // Provides exclusive access to all pages, and ensures they are walkable. |
| 451 class ExclusivePageIterator : ValueObject { | 449 class ExclusivePageIterator : ValueObject { |
| 452 public: | 450 public: |
| 453 explicit ExclusivePageIterator(const PageSpace* space) | 451 explicit ExclusivePageIterator(const PageSpace* space) |
| 454 : space_(space), ml_(space->pages_lock_) { | 452 : space_(space), ml_(space->pages_lock_) { |
| 455 space_->MakeIterable(); | 453 space_->MakeIterable(); |
| 456 page_ = space_->pages_; | 454 page_ = space_->pages_; |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 freelist_[HeapPage::kData].Free(bump_top_, remaining); | 1000 freelist_[HeapPage::kData].Free(bump_top_, remaining); |
| 1003 } | 1001 } |
| 1004 } | 1002 } |
| 1005 bump_top_ = reinterpret_cast<uword>(block); | 1003 bump_top_ = reinterpret_cast<uword>(block); |
| 1006 bump_end_ = bump_top_ + block_size; | 1004 bump_end_ = bump_top_ + block_size; |
| 1007 remaining = block_size; | 1005 remaining = block_size; |
| 1008 } | 1006 } |
| 1009 ASSERT(remaining >= size); | 1007 ASSERT(remaining >= size); |
| 1010 uword result = bump_top_; | 1008 uword result = bump_top_; |
| 1011 bump_top_ += size; | 1009 bump_top_ += size; |
| 1012 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), | 1010 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 1013 (size >> kWordSizeLog2)); | 1011 (size >> kWordSizeLog2)); |
| 1014 // Note: Remaining block is unwalkable until MakeIterable is called. | 1012 // Note: Remaining block is unwalkable until MakeIterable is called. |
| 1015 #ifdef DEBUG | 1013 #ifdef DEBUG |
| 1016 if (bump_top_ < bump_end_) { | 1014 if (bump_top_ < bump_end_) { |
| 1017 // Fail fast if we try to walk the remaining block. | 1015 // Fail fast if we try to walk the remaining block. |
| 1018 COMPILE_ASSERT(kIllegalCid == 0); | 1016 COMPILE_ASSERT(kIllegalCid == 0); |
| 1019 *reinterpret_cast<uword*>(bump_top_) = 0; | 1017 *reinterpret_cast<uword*>(bump_top_) = 0; |
| 1020 } | 1018 } |
| 1021 #endif // DEBUG | 1019 #endif // DEBUG |
| 1022 return result; | 1020 return result; |
| 1023 } | 1021 } |
| 1024 | 1022 |
| 1025 | 1023 |
| 1026 uword PageSpace::TryAllocateDataBump(intptr_t size, | 1024 uword PageSpace::TryAllocateDataBump(intptr_t size, |
| 1027 GrowthPolicy growth_policy) { | 1025 GrowthPolicy growth_policy) { |
| 1028 return TryAllocateDataBumpInternal(size, growth_policy, false); | 1026 return TryAllocateDataBumpInternal(size, growth_policy, false); |
| 1029 } | 1027 } |
| 1030 | 1028 |
| 1031 | 1029 |
| 1032 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size, | 1030 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size, |
| 1033 GrowthPolicy growth_policy) { | 1031 GrowthPolicy growth_policy) { |
| 1034 return TryAllocateDataBumpInternal(size, growth_policy, true); | 1032 return TryAllocateDataBumpInternal(size, growth_policy, true); |
| 1035 } | 1033 } |
| 1036 | 1034 |
| 1037 | 1035 |
| 1038 uword PageSpace::TryAllocatePromoLocked(intptr_t size, | 1036 uword PageSpace::TryAllocatePromoLocked(intptr_t size, |
| 1039 GrowthPolicy growth_policy) { | 1037 GrowthPolicy growth_policy) { |
| 1040 FreeList* freelist = &freelist_[HeapPage::kData]; | 1038 FreeList* freelist = &freelist_[HeapPage::kData]; |
| 1041 uword result = freelist->TryAllocateSmallLocked(size); | 1039 uword result = freelist->TryAllocateSmallLocked(size); |
| 1042 if (result != 0) { | 1040 if (result != 0) { |
| 1043 AtomicOperations::FetchAndIncrementBy(&(usage_.used_in_words), | 1041 AtomicOperations::IncrementBy(&(usage_.used_in_words), |
| 1044 (size >> kWordSizeLog2)); | 1042 (size >> kWordSizeLog2)); |
| 1045 return result; | 1043 return result; |
| 1046 } | 1044 } |
| 1047 result = TryAllocateDataBumpLocked(size, growth_policy); | 1045 result = TryAllocateDataBumpLocked(size, growth_policy); |
| 1048 if (result != 0) return result; | 1046 if (result != 0) return result; |
| 1049 return TryAllocateDataLocked(size, growth_policy); | 1047 return TryAllocateDataLocked(size, growth_policy); |
| 1050 } | 1048 } |
| 1051 | 1049 |
| 1052 | 1050 |
| 1053 uword PageSpace::TryAllocateSmiInitializedLocked(intptr_t size, | 1051 uword PageSpace::TryAllocateSmiInitializedLocked(intptr_t size, |
| 1054 GrowthPolicy growth_policy) { | 1052 GrowthPolicy growth_policy) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 return 0; | 1219 return 0; |
| 1222 } else { | 1220 } else { |
| 1223 ASSERT(total_time >= gc_time); | 1221 ASSERT(total_time >= gc_time); |
| 1224 int result = static_cast<int>((static_cast<double>(gc_time) / | 1222 int result = static_cast<int>((static_cast<double>(gc_time) / |
| 1225 static_cast<double>(total_time)) * 100); | 1223 static_cast<double>(total_time)) * 100); |
| 1226 return result; | 1224 return result; |
| 1227 } | 1225 } |
| 1228 } | 1226 } |
| 1229 | 1227 |
| 1230 } // namespace dart | 1228 } // namespace dart |
| OLD | NEW |