// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compiler/zone-pool.h" namespace v8 { namespace internal { namespace compiler { ZonePool::StatsScope::StatsScope(ZonePool* zone_pool) : zone_pool_(zone_pool), total_allocated_bytes_at_start_(zone_pool->GetTotalAllocatedBytes()), max_allocated_bytes_(0) { zone_pool_->stats_.push_back(this); for (Zone* zone : zone_pool_->used_) { size_t size = static_cast<size_t>(zone->allocation_size()); std::pair<InitialValues::iterator, bool> res = initial_values_.insert(std::make_pair(zone, size)); USE(res); DCHECK(res.second); } } ZonePool::StatsScope::~StatsScope() { DCHECK_EQ(zone_pool_->stats_.back(), this); zone_pool_->stats_.pop_back(); } size_t ZonePool::StatsScope::GetMaxAllocatedBytes() { return std::max(max_allocated_bytes_, GetCurrentAllocatedBytes()); } size_t ZonePool::StatsScope::GetCurrentAllocatedBytes() { size_t total = 0; for (Zone* zone : zone_pool_->used_) { total += static_cast<size_t>(zone->allocation_size()); // Adjust for initial values. InitialValues::iterator it = initial_values_.find(zone); if (it != initial_values_.end()) { total -= it->second; } } return total; } size_t ZonePool::StatsScope::GetTotalAllocatedBytes() { return zone_pool_->GetTotalAllocatedBytes() - total_allocated_bytes_at_start_; } void ZonePool::StatsScope::ZoneReturned(Zone* zone) { size_t current_total = GetCurrentAllocatedBytes(); // Update max. max_allocated_bytes_ = std::max(max_allocated_bytes_, current_total); // Drop zone from initial value map. InitialValues::iterator it = initial_values_.find(zone); if (it != initial_values_.end()) { initial_values_.erase(it); } } ZonePool::ZonePool(base::AccountingAllocator* allocator) : max_allocated_bytes_(0), total_deleted_bytes_(0), allocator_(allocator) {} ZonePool::~ZonePool() { DCHECK(used_.empty()); DCHECK(stats_.empty()); for (Zone* zone : unused_) { delete zone; } } size_t ZonePool::GetMaxAllocatedBytes() { return std::max(max_allocated_bytes_, GetCurrentAllocatedBytes()); } size_t ZonePool::GetCurrentAllocatedBytes() { size_t total = 0; for (Zone* zone : used_) { total += static_cast<size_t>(zone->allocation_size()); } return total; } size_t ZonePool::GetTotalAllocatedBytes() { return total_deleted_bytes_ + GetCurrentAllocatedBytes(); } Zone* ZonePool::NewEmptyZone() { Zone* zone; // Grab a zone from pool if possible. if (!unused_.empty()) { zone = unused_.back(); unused_.pop_back(); } else { zone = new Zone(allocator_); } used_.push_back(zone); DCHECK_EQ(0u, zone->allocation_size()); return zone; } void ZonePool::ReturnZone(Zone* zone) { size_t current_total = GetCurrentAllocatedBytes(); // Update max. max_allocated_bytes_ = std::max(max_allocated_bytes_, current_total); // Update stats. for (StatsScope* stat_scope : stats_) { stat_scope->ZoneReturned(zone); } // Remove from used. Used::iterator it = std::find(used_.begin(), used_.end(), zone); DCHECK(it != used_.end()); used_.erase(it); total_deleted_bytes_ += static_cast<size_t>(zone->allocation_size()); // Delete zone or clear and stash on unused_. if (unused_.size() >= kMaxUnusedSize) { delete zone; } else { zone->DeleteAll(); DCHECK_EQ(0u, zone->allocation_size()); unused_.push_back(zone); } } } // namespace compiler } // namespace internal } // namespace v8