1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
//===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the BumpPtrAllocator interface.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Recycler.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Streams.h"
#include <ostream>
using namespace llvm;
//===----------------------------------------------------------------------===//
// MemRegion class implementation
//===----------------------------------------------------------------------===//
namespace {
/// MemRegion - This is one chunk of the BumpPtrAllocator.
class MemRegion {
unsigned RegionSize;
MemRegion *Next;
char *NextPtr;
public:
void Init(unsigned size, unsigned Alignment, MemRegion *next) {
RegionSize = size;
Next = next;
NextPtr = (char*)(this+1);
// Align NextPtr.
NextPtr = (char*)((intptr_t)(NextPtr+Alignment-1) &
~(intptr_t)(Alignment-1));
}
const MemRegion *getNext() const { return Next; }
unsigned getNumBytesAllocated() const {
return NextPtr-(const char*)this;
}
/// Allocate - Allocate and return at least the specified number of bytes.
///
void *Allocate(size_t AllocSize, size_t Alignment, MemRegion **RegPtr) {
char* Result = (char*) (((uintptr_t) (NextPtr+Alignment-1))
& ~((uintptr_t) Alignment-1));
// Speculate the new value of NextPtr.
char* NextPtrTmp = Result + AllocSize;
// If we are still within the current region, return Result.
if (unsigned (NextPtrTmp - (char*) this) <= RegionSize) {
NextPtr = NextPtrTmp;
return Result;
}
// Otherwise, we have to allocate a new chunk. Create one twice as big as
// this one.
MemRegion *NewRegion = (MemRegion *)malloc(RegionSize*2);
NewRegion->Init(RegionSize*2, Alignment, this);
// Update the current "first region" pointer to point to the new region.
*RegPtr = NewRegion;
// Try allocating from it now.
return NewRegion->Allocate(AllocSize, Alignment, RegPtr);
}
/// Deallocate - Recursively release all memory for this and its next regions
/// to the system.
void Deallocate() {
MemRegion *next = Next;
free(this);
if (next)
next->Deallocate();
}
/// DeallocateAllButLast - Recursively release all memory for this and its
/// next regions to the system stopping at the last region in the list.
/// Returns the pointer to the last region.
MemRegion *DeallocateAllButLast() {
MemRegion *next = Next;
if (!next)
return this;
free(this);
return next->DeallocateAllButLast();
}
};
}
//===----------------------------------------------------------------------===//
// BumpPtrAllocator class implementation
//===----------------------------------------------------------------------===//
BumpPtrAllocator::BumpPtrAllocator() {
TheMemory = malloc(4096);
((MemRegion*)TheMemory)->Init(4096, 1, 0);
}
BumpPtrAllocator::~BumpPtrAllocator() {
((MemRegion*)TheMemory)->Deallocate();
}
void BumpPtrAllocator::Reset() {
MemRegion *MRP = (MemRegion*)TheMemory;
MRP = MRP->DeallocateAllButLast();
MRP->Init(4096, 1, 0);
TheMemory = MRP;
}
void *BumpPtrAllocator::Allocate(size_t Size, size_t Align) {
MemRegion *MRP = (MemRegion*)TheMemory;
void *Ptr = MRP->Allocate(Size, Align, &MRP);
TheMemory = MRP;
return Ptr;
}
void BumpPtrAllocator::PrintStats() const {
unsigned BytesUsed = 0;
unsigned NumRegions = 0;
const MemRegion *R = (MemRegion*)TheMemory;
for (; R; R = R->getNext(), ++NumRegions)
BytesUsed += R->getNumBytesAllocated();
cerr << "\nNumber of memory regions: " << NumRegions << "\n";
cerr << "Bytes allocated: " << BytesUsed << "\n";
}
void llvm::PrintRecyclerStats(size_t Size,
size_t Align,
size_t FreeListSize) {
cerr << "Recycler element size: " << Size << '\n';
cerr << "Recycler element alignment: " << Align << '\n';
cerr << "Number of elements free for recycling: " << FreeListSize << '\n';
}
|