1 // Copyright 2014 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 #include "src/compiler/zone-pool.h" 6 7 namespace v8 { 8 namespace internal { 9 namespace compiler { 10 11 ZonePool::StatsScope::StatsScope(ZonePool* zone_pool) 12 : zone_pool_(zone_pool), 13 total_allocated_bytes_at_start_(zone_pool->GetTotalAllocatedBytes()), 14 max_allocated_bytes_(0) { 15 zone_pool_->stats_.push_back(this); 16 for (Zone* zone : zone_pool_->used_) { 17 size_t size = static_cast<size_t>(zone->allocation_size()); 18 std::pair<InitialValues::iterator, bool> res = 19 initial_values_.insert(std::make_pair(zone, size)); 20 USE(res); 21 DCHECK(res.second); 22 } 23 } 24 25 26 ZonePool::StatsScope::~StatsScope() { 27 DCHECK_EQ(zone_pool_->stats_.back(), this); 28 zone_pool_->stats_.pop_back(); 29 } 30 31 32 size_t ZonePool::StatsScope::GetMaxAllocatedBytes() { 33 return std::max(max_allocated_bytes_, GetCurrentAllocatedBytes()); 34 } 35 36 37 size_t ZonePool::StatsScope::GetCurrentAllocatedBytes() { 38 size_t total = 0; 39 for (Zone* zone : zone_pool_->used_) { 40 total += static_cast<size_t>(zone->allocation_size()); 41 // Adjust for initial values. 42 InitialValues::iterator it = initial_values_.find(zone); 43 if (it != initial_values_.end()) { 44 total -= it->second; 45 } 46 } 47 return total; 48 } 49 50 51 size_t ZonePool::StatsScope::GetTotalAllocatedBytes() { 52 return zone_pool_->GetTotalAllocatedBytes() - total_allocated_bytes_at_start_; 53 } 54 55 56 void ZonePool::StatsScope::ZoneReturned(Zone* zone) { 57 size_t current_total = GetCurrentAllocatedBytes(); 58 // Update max. 59 max_allocated_bytes_ = std::max(max_allocated_bytes_, current_total); 60 // Drop zone from initial value map. 61 InitialValues::iterator it = initial_values_.find(zone); 62 if (it != initial_values_.end()) { 63 initial_values_.erase(it); 64 } 65 } 66 67 ZonePool::ZonePool(base::AccountingAllocator* allocator) 68 : max_allocated_bytes_(0), total_deleted_bytes_(0), allocator_(allocator) {} 69 70 ZonePool::~ZonePool() { 71 DCHECK(used_.empty()); 72 DCHECK(stats_.empty()); 73 for (Zone* zone : unused_) { 74 delete zone; 75 } 76 } 77 78 79 size_t ZonePool::GetMaxAllocatedBytes() { 80 return std::max(max_allocated_bytes_, GetCurrentAllocatedBytes()); 81 } 82 83 84 size_t ZonePool::GetCurrentAllocatedBytes() { 85 size_t total = 0; 86 for (Zone* zone : used_) { 87 total += static_cast<size_t>(zone->allocation_size()); 88 } 89 return total; 90 } 91 92 93 size_t ZonePool::GetTotalAllocatedBytes() { 94 return total_deleted_bytes_ + GetCurrentAllocatedBytes(); 95 } 96 97 98 Zone* ZonePool::NewEmptyZone() { 99 Zone* zone; 100 // Grab a zone from pool if possible. 101 if (!unused_.empty()) { 102 zone = unused_.back(); 103 unused_.pop_back(); 104 } else { 105 zone = new Zone(allocator_); 106 } 107 used_.push_back(zone); 108 DCHECK_EQ(0u, zone->allocation_size()); 109 return zone; 110 } 111 112 113 void ZonePool::ReturnZone(Zone* zone) { 114 size_t current_total = GetCurrentAllocatedBytes(); 115 // Update max. 116 max_allocated_bytes_ = std::max(max_allocated_bytes_, current_total); 117 // Update stats. 118 for (StatsScope* stat_scope : stats_) { 119 stat_scope->ZoneReturned(zone); 120 } 121 // Remove from used. 122 Used::iterator it = std::find(used_.begin(), used_.end(), zone); 123 DCHECK(it != used_.end()); 124 used_.erase(it); 125 total_deleted_bytes_ += static_cast<size_t>(zone->allocation_size()); 126 // Delete zone or clear and stash on unused_. 127 if (unused_.size() >= kMaxUnusedSize) { 128 delete zone; 129 } else { 130 zone->DeleteAll(); 131 DCHECK_EQ(0u, zone->allocation_size()); 132 unused_.push_back(zone); 133 } 134 } 135 136 } // namespace compiler 137 } // namespace internal 138 } // namespace v8 139