Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: runtime/vm/pages.cc

Issue 1580813003: Use atomic operations to increment/decrement memory usage counts as multiple threads could be alloc… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: self-code-review Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/atomic_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/atomic_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698