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 (auto 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 68 ZonePool::ZonePool() : max_allocated_bytes_(0), total_deleted_bytes_(0) {} 69 70 71 ZonePool::~ZonePool() { 72 DCHECK(used_.empty()); 73 DCHECK(stats_.empty()); 74 for (Zone* zone : unused_) { 75 delete zone; 76 } 77 } 78 79 80 size_t ZonePool::GetMaxAllocatedBytes() { 81 return std::max(max_allocated_bytes_, GetCurrentAllocatedBytes()); 82 } 83 84 85 size_t ZonePool::GetCurrentAllocatedBytes() { 86 size_t total = 0; 87 for (Zone* zone : used_) { 88 total += static_cast<size_t>(zone->allocation_size()); 89 } 90 return total; 91 } 92 93 94 size_t ZonePool::GetTotalAllocatedBytes() { 95 return total_deleted_bytes_ + GetCurrentAllocatedBytes(); 96 } 97 98 99 Zone* ZonePool::NewEmptyZone() { 100 Zone* zone; 101 // Grab a zone from pool if possible. 102 if (!unused_.empty()) { 103 zone = unused_.back(); 104 unused_.pop_back(); 105 } else { 106 zone = new Zone(); 107 } 108 used_.push_back(zone); 109 DCHECK_EQ(0u, zone->allocation_size()); 110 return zone; 111 } 112 113 114 void ZonePool::ReturnZone(Zone* zone) { 115 size_t current_total = GetCurrentAllocatedBytes(); 116 // Update max. 117 max_allocated_bytes_ = std::max(max_allocated_bytes_, current_total); 118 // Update stats. 119 for (auto stat_scope : stats_) { 120 stat_scope->ZoneReturned(zone); 121 } 122 // Remove from used. 123 Used::iterator it = std::find(used_.begin(), used_.end(), zone); 124 DCHECK(it != used_.end()); 125 used_.erase(it); 126 total_deleted_bytes_ += static_cast<size_t>(zone->allocation_size()); 127 // Delete zone or clear and stash on unused_. 128 if (unused_.size() >= kMaxUnusedSize) { 129 delete zone; 130 } else { 131 zone->DeleteAll(); 132 DCHECK_EQ(0u, zone->allocation_size()); 133 unused_.push_back(zone); 134 } 135 } 136 137 } // namespace compiler 138 } // namespace internal 139 } // namespace v8 140