1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_ZONE_ACCOUNTING_ALLOCATOR_H_ 6 #define V8_ZONE_ACCOUNTING_ALLOCATOR_H_ 7 8 #include "include/v8-platform.h" 9 #include "include/v8.h" 10 #include "src/base/atomic-utils.h" 11 #include "src/base/atomicops.h" 12 #include "src/base/macros.h" 13 #include "src/base/platform/mutex.h" 14 #include "src/base/platform/semaphore.h" 15 #include "src/base/platform/time.h" 16 #include "src/zone/zone-segment.h" 17 #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck 18 19 namespace v8 { 20 namespace internal { 21 22 class V8_EXPORT_PRIVATE AccountingAllocator { 23 public: 24 static const size_t kMaxPoolSize = 8ul * KB; 25 26 AccountingAllocator(); 27 virtual ~AccountingAllocator(); 28 29 // Gets an empty segment from the pool or creates a new one. 30 virtual Segment* GetSegment(size_t bytes); 31 // Return unneeded segments to either insert them into the pool or release 32 // them if the pool is already full or memory pressure is high. 33 virtual void ReturnSegment(Segment* memory); 34 35 size_t GetCurrentMemoryUsage() const; 36 size_t GetMaxMemoryUsage() const; 37 38 size_t GetCurrentPoolSize() const; 39 40 void MemoryPressureNotification(MemoryPressureLevel level); 41 // Configures the zone segment pool size limits so the pool does not 42 // grow bigger than max_pool_size. 43 // TODO(heimbuef): Do not accept segments to pool that are larger than 44 // their size class requires. Sometimes the zones generate weird segments. 45 void ConfigureSegmentPool(const size_t max_pool_size); 46 ZoneCreation(const Zone * zone)47 virtual void ZoneCreation(const Zone* zone) {} ZoneDestruction(const Zone * zone)48 virtual void ZoneDestruction(const Zone* zone) {} 49 50 private: 51 FRIEND_TEST(Zone, SegmentPoolConstraints); 52 53 static const size_t kMinSegmentSizePower = 13; 54 static const size_t kMaxSegmentSizePower = 18; 55 56 STATIC_ASSERT(kMinSegmentSizePower <= kMaxSegmentSizePower); 57 58 static const size_t kNumberBuckets = 59 1 + kMaxSegmentSizePower - kMinSegmentSizePower; 60 61 // Allocates a new segment. Returns nullptr on failed allocation. 62 Segment* AllocateSegment(size_t bytes); 63 void FreeSegment(Segment* memory); 64 65 // Returns a segment from the pool of at least the requested size. 66 Segment* GetSegmentFromPool(size_t requested_size); 67 // Trys to add a segment to the pool. Returns false if the pool is full. 68 bool AddSegmentToPool(Segment* segment); 69 70 // Empties the pool and puts all its contents onto the garbage stack. 71 void ClearPool(); 72 73 Segment* unused_segments_heads_[kNumberBuckets]; 74 75 size_t unused_segments_sizes_[kNumberBuckets]; 76 size_t unused_segments_max_sizes_[kNumberBuckets]; 77 78 base::Mutex unused_segments_mutex_; 79 80 base::AtomicWord current_memory_usage_ = 0; 81 base::AtomicWord max_memory_usage_ = 0; 82 base::AtomicWord current_pool_size_ = 0; 83 84 base::AtomicValue<MemoryPressureLevel> memory_pressure_level_; 85 86 DISALLOW_COPY_AND_ASSIGN(AccountingAllocator); 87 }; 88 89 } // namespace internal 90 } // namespace v8 91 92 #endif // V8_ZONE_ACCOUNTING_ALLOCATOR_H_ 93