cb7aa79b12
We expect that the majority of malloc'd memory held by V8 is allocated in Zone objects. Introduce an Allocator class that is used by Zones to manage memory, and allows for querying the current usage. BUG=none R=titzer@chromium.org,bmeurer@chromium.org,jarin@chromium.org LOG=n TBR=rossberg@chromium.org Review URL: https://codereview.chromium.org/1847543002 Cr-Commit-Position: refs/heads/master@{#35196}
139 lines
3.5 KiB
C++
139 lines
3.5 KiB
C++
// 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
|