xref: /aosp_15_r20/external/leveldb/util/arena.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
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 Worker Arena::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 Worker Arena::~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 Worker char* 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 Worker char* 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 Worker char* 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