1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors. 4*9507f98cSAndroid Build Coastguard Worker 5*9507f98cSAndroid Build Coastguard Worker #include "util/arena.h" 6*9507f98cSAndroid Build Coastguard Worker 7*9507f98cSAndroid Build Coastguard Worker namespace leveldb { 8*9507f98cSAndroid Build Coastguard Worker 9*9507f98cSAndroid Build Coastguard Worker static const int kBlockSize = 4096; 10*9507f98cSAndroid Build Coastguard Worker Arena()11*9507f98cSAndroid Build Coastguard WorkerArena::Arena() 12*9507f98cSAndroid Build Coastguard Worker : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {} 13*9507f98cSAndroid Build Coastguard Worker ~Arena()14*9507f98cSAndroid Build Coastguard WorkerArena::~Arena() { 15*9507f98cSAndroid Build Coastguard Worker for (size_t i = 0; i < blocks_.size(); i++) { 16*9507f98cSAndroid Build Coastguard Worker delete[] blocks_[i]; 17*9507f98cSAndroid Build Coastguard Worker } 18*9507f98cSAndroid Build Coastguard Worker } 19*9507f98cSAndroid Build Coastguard Worker AllocateFallback(size_t bytes)20*9507f98cSAndroid Build Coastguard Workerchar* Arena::AllocateFallback(size_t bytes) { 21*9507f98cSAndroid Build Coastguard Worker if (bytes > kBlockSize / 4) { 22*9507f98cSAndroid Build Coastguard Worker // Object is more than a quarter of our block size. Allocate it separately 23*9507f98cSAndroid Build Coastguard Worker // to avoid wasting too much space in leftover bytes. 24*9507f98cSAndroid Build Coastguard Worker char* result = AllocateNewBlock(bytes); 25*9507f98cSAndroid Build Coastguard Worker return result; 26*9507f98cSAndroid Build Coastguard Worker } 27*9507f98cSAndroid Build Coastguard Worker 28*9507f98cSAndroid Build Coastguard Worker // We waste the remaining space in the current block. 29*9507f98cSAndroid Build Coastguard Worker alloc_ptr_ = AllocateNewBlock(kBlockSize); 30*9507f98cSAndroid Build Coastguard Worker alloc_bytes_remaining_ = kBlockSize; 31*9507f98cSAndroid Build Coastguard Worker 32*9507f98cSAndroid Build Coastguard Worker char* result = alloc_ptr_; 33*9507f98cSAndroid Build Coastguard Worker alloc_ptr_ += bytes; 34*9507f98cSAndroid Build Coastguard Worker alloc_bytes_remaining_ -= bytes; 35*9507f98cSAndroid Build Coastguard Worker return result; 36*9507f98cSAndroid Build Coastguard Worker } 37*9507f98cSAndroid Build Coastguard Worker AllocateAligned(size_t bytes)38*9507f98cSAndroid Build Coastguard Workerchar* Arena::AllocateAligned(size_t bytes) { 39*9507f98cSAndroid Build Coastguard Worker const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; 40*9507f98cSAndroid Build Coastguard Worker static_assert((align & (align - 1)) == 0, 41*9507f98cSAndroid Build Coastguard Worker "Pointer size should be a power of 2"); 42*9507f98cSAndroid Build Coastguard Worker size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align - 1); 43*9507f98cSAndroid Build Coastguard Worker size_t slop = (current_mod == 0 ? 0 : align - current_mod); 44*9507f98cSAndroid Build Coastguard Worker size_t needed = bytes + slop; 45*9507f98cSAndroid Build Coastguard Worker char* result; 46*9507f98cSAndroid Build Coastguard Worker if (needed <= alloc_bytes_remaining_) { 47*9507f98cSAndroid Build Coastguard Worker result = alloc_ptr_ + slop; 48*9507f98cSAndroid Build Coastguard Worker alloc_ptr_ += needed; 49*9507f98cSAndroid Build Coastguard Worker alloc_bytes_remaining_ -= needed; 50*9507f98cSAndroid Build Coastguard Worker } else { 51*9507f98cSAndroid Build Coastguard Worker // AllocateFallback always returned aligned memory 52*9507f98cSAndroid Build Coastguard Worker result = AllocateFallback(bytes); 53*9507f98cSAndroid Build Coastguard Worker } 54*9507f98cSAndroid Build Coastguard Worker assert((reinterpret_cast<uintptr_t>(result) & (align - 1)) == 0); 55*9507f98cSAndroid Build Coastguard Worker return result; 56*9507f98cSAndroid Build Coastguard Worker } 57*9507f98cSAndroid Build Coastguard Worker AllocateNewBlock(size_t block_bytes)58*9507f98cSAndroid Build Coastguard Workerchar* Arena::AllocateNewBlock(size_t block_bytes) { 59*9507f98cSAndroid Build Coastguard Worker char* result = new char[block_bytes]; 60*9507f98cSAndroid Build Coastguard Worker blocks_.push_back(result); 61*9507f98cSAndroid Build Coastguard Worker memory_usage_.fetch_add(block_bytes + sizeof(char*), 62*9507f98cSAndroid Build Coastguard Worker std::memory_order_relaxed); 63*9507f98cSAndroid Build Coastguard Worker return result; 64*9507f98cSAndroid Build Coastguard Worker } 65*9507f98cSAndroid Build Coastguard Worker 66*9507f98cSAndroid Build Coastguard Worker } // namespace leveldb 67