blob: b9317078db791969702cb5e0468d8a862f9a612b [file] [log] [blame]
//===- PoolAllocator.h - Pool allocator runtime interface file --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface which is implemented by the LLVM pool
// allocator runtime library.
//
// Note: Most of this runtime library is templated based on a PoolTraits
// instance. This allows the normal pool allocator to use standard pointers and
// long's to represent things, but allows the pointer compression runtime
// library use pool indexes which are smaller. Using smaller indexes reduces
// the minimum object size on a 64-bit system from 16 to 8 bytes, and reduces
// the object header size to 4 bytes (from 8).
//
//===----------------------------------------------------------------------===//
#ifndef POOLALLOCATOR_RUNTIME_H
#define POOLALLOCATOR_RUNTIME_H
#include <assert.h>
#include <pthread.h>
template<typename PoolTraits>
struct PoolSlab;
template<typename PoolTraits>
struct FreedNodeHeader;
// NormalPoolTraits - This describes normal pool allocation pools, which can
// address the entire heap, and are made out of multiple chunks of memory. The
// object header is a full machine word, and pointers into the heap are native
// pointers.
struct NormalPoolTraits {
typedef unsigned long NodeHeaderType;
enum {
UseLargeArrayObjects = 1,
CanGrowPool = 1
};
// Pointers are just pointers.
typedef FreedNodeHeader<NormalPoolTraits>* FreeNodeHeaderPtrTy;
static const char *getSuffix() { return ""; }
/// DerefFNHPtr - Given an index into the pool, return a pointer to the
/// FreeNodeHeader object.
static FreedNodeHeader<NormalPoolTraits>*
IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
return P;
}
static FreeNodeHeaderPtrTy
FNHPtrToIndex(FreedNodeHeader<NormalPoolTraits>* FNHP, void *PoolBase) {
return FNHP;
}
};
// CompressedPoolTraits - This describes a statically pointer compressed pool,
// which is known to be <= 2^32 bytes in size (even on a 64-bit machine), and is
// made out of a single contiguous block. The meta-data to represent the pool
// uses 32-bit indexes from the start of the pool instead of full pointers to
// decrease the minimum object size.
struct CompressedPoolTraits {
typedef unsigned NodeHeaderType;
enum {
UseLargeArrayObjects = 0,
CanGrowPool = 0
};
// Represent pointers with indexes from the pool base.
typedef unsigned FreeNodeHeaderPtrTy;
static const char *getSuffix() { return "_pc"; }
/// DerefFNHPtr - Given an index into the pool, return a pointer to the
/// FreeNodeHeader object.
static FreedNodeHeader<CompressedPoolTraits>*
IndexToFNHPtr(FreeNodeHeaderPtrTy P, void *PoolBase) {
return (FreedNodeHeader<CompressedPoolTraits>*)((char*)PoolBase + P);
}
static FreeNodeHeaderPtrTy
FNHPtrToIndex(FreedNodeHeader<CompressedPoolTraits>* FNHP, void *PoolBase) {
assert(FNHP && PoolBase && "Can't handle null FHNP!");
return (char*)FNHP - (char*)PoolBase;
}
};
// NodeHeader - Each block of memory is preceeded in the the pool by one of
// these headers.
template<typename PoolTraits>
struct NodeHeader {
typename PoolTraits::NodeHeaderType Size;
};
// When objects are on the free list, we pretend they have this header.
template<typename PoolTraits>
struct FreedNodeHeader {
// NormalHeader - This is the normal node header that is on allocated or free
// blocks.
NodeHeader<PoolTraits> Header;
// Next - The next object in the free list.
typename PoolTraits::FreeNodeHeaderPtrTy Next;
// Prev - The node that points to this node on the free list. This is null
// if it is the first node in one of the two free lists.
typename PoolTraits::FreeNodeHeaderPtrTy Prev;
};
// Large Arrays are passed on to directly malloc, and are not necessarily page
// aligned. These arrays are marked by setting the object size preheader to ~1.
// LargeArrays are on their own list to allow for efficient deletion.
struct LargeArrayHeader {
LargeArrayHeader **Prev, *Next;
// Size - This contains the size of the object.
unsigned long Size;
// Marker: this is the ObjectSize marker which MUST BE THE LAST ELEMENT of
// this header!
unsigned long Marker;
void UnlinkFromList() {
*Prev = Next;
if (Next)
Next->Prev = Prev;
}
void LinkIntoList(LargeArrayHeader **List) {
Next = *List;
if (Next)
Next->Prev = &Next;
*List = this;
Prev = List;
}
};
template<typename PoolTraits>
struct PoolTy {
// Slabs - the list of slabs in this pool. NOTE: This must remain the first
// memory of this structure for the pointer compression pass.
PoolSlab<PoolTraits> *Slabs;
// The free node lists for objects of various sizes.
typename PoolTraits::FreeNodeHeaderPtrTy ObjFreeList;
typename PoolTraits::FreeNodeHeaderPtrTy OtherFreeList;
// Alignment - The required alignment of allocations the pool in bytes.
unsigned Alignment;
// The declared size of the pool, just kept for the record.
unsigned DeclaredSize;
// LargeArrays - A doubly linked list of large array chunks, dynamically
// allocated with malloc.
LargeArrayHeader *LargeArrays;
// The size to allocate for the next slab.
unsigned AllocSize;
// NumObjects - the number of poolallocs for this pool.
unsigned NumObjects;
// BytesAllocated - The total number of bytes ever allocated from this pool.
// Together with NumObjects, allows us to calculate average object size.
unsigned BytesAllocated;
// Lock for the pool
pthread_mutex_t pool_lock;
// Thread reference count for the pool
int thread_refcount;
};
extern "C" {
void poolinit(PoolTy<NormalPoolTraits> *Pool,
unsigned DeclaredSize, unsigned ObjAlignment);
void poolmakeunfreeable(PoolTy<NormalPoolTraits> *Pool);
void pooldestroy(PoolTy<NormalPoolTraits> *Pool);
void *poolalloc(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes);
void *poolcalloc(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes, unsigned);
void *poolrealloc(PoolTy<NormalPoolTraits> *Pool,
void *Node, unsigned NumBytes);
void *poolmemalign(PoolTy<NormalPoolTraits> *Pool,
unsigned Alignment, unsigned NumBytes);
void poolfree(PoolTy<NormalPoolTraits> *Pool, void *Node);
/// poolobjsize - Return the size of the object at the specified address, in
/// the specified pool. Note that this cannot be used in normal cases, as it
/// is completely broken if things land in the system heap. Perhaps in the
/// future. :(
///
unsigned poolobjsize(PoolTy<NormalPoolTraits> *Pool, void *Node);
// Bump pointer pool library. This is a pool implementation that does not
// support frees or reallocs to the pool. As such, it can be much more
// efficient and simpler than a general pool implementation.
void poolinit_bp(PoolTy<NormalPoolTraits> *Pool, unsigned ObjAlignment);
void *poolalloc_bp(PoolTy<NormalPoolTraits> *Pool, unsigned NumBytes);
void pooldestroy_bp(PoolTy<NormalPoolTraits> *Pool);
// Pointer Compression runtime library. Most of these are just wrappers
// around the normal pool routines.
void *poolinit_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned NodeSize,
unsigned ObjAlignment);
void pooldestroy_pc(PoolTy<CompressedPoolTraits> *Pool);
unsigned long long poolalloc_pc(PoolTy<CompressedPoolTraits> *Pool,
unsigned NumBytes);
void poolfree_pc(PoolTy<CompressedPoolTraits> *Pool, unsigned long long Node);
//void *poolmemalign_pc(PoolTy *Pool, unsigned Alignment, unsigned NumBytes);
unsigned long long poolrealloc_pc(PoolTy<CompressedPoolTraits> *Pool,
unsigned long long Node, unsigned NumBytes);
// Alternate Pointer Compression runtime library. Most of these are just
// wrappers around the normal pool routines.
void *poolinit_pca(PoolTy<CompressedPoolTraits> *Pool, unsigned NodeSize,
unsigned ObjAlignment);
void pooldestroy_pca(PoolTy<CompressedPoolTraits> *Pool);
void* poolalloc_pca(PoolTy<CompressedPoolTraits> *Pool,
unsigned NumBytes);
void poolfree_pca(PoolTy<CompressedPoolTraits> *Pool, void* Node);
void* poolrealloc_pca(PoolTy<CompressedPoolTraits> *Pool,
void* Node, unsigned NumBytes);
// Access tracing runtime library support.
void poolaccesstraceinit(void);
void poolaccesstrace(void *Ptr, void *PD);
// Auxiliary functions for thread support
#ifdef USE_DYNCALL
int poolalloc_pthread_create(pthread_t* thread,
const pthread_attr_t* attr,
void *(*start_routine)(void*), int num_pools, ...);
#endif
}
#endif