mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 05:18:44 +00:00
102 lines
3 KiB
C++
102 lines
3 KiB
C++
/*++
|
|
Copyright (c) 2018 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sat_allocator.h
|
|
|
|
Abstract:
|
|
|
|
Small object allocator suitable for clauses
|
|
|
|
Author:
|
|
|
|
Nikolaj bjorner (nbjorner) 2018-04-26.
|
|
|
|
Revision History:
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
#include "util/vector.h"
|
|
#include "util/machine.h"
|
|
|
|
class sat_allocator {
|
|
static const unsigned CHUNK_SIZE = (1 << 16) - sizeof(char*);
|
|
static const unsigned SMALL_OBJ_SIZE = 512;
|
|
static const unsigned MASK = ((1 << PTR_ALIGNMENT) - 1);
|
|
static const unsigned NUM_FREE = 1 + (SMALL_OBJ_SIZE >> PTR_ALIGNMENT);
|
|
struct chunk {
|
|
char * m_curr;
|
|
char m_data[CHUNK_SIZE];
|
|
chunk():m_curr(m_data) {}
|
|
};
|
|
char const * m_id;
|
|
size_t m_alloc_size;
|
|
ptr_vector<chunk> m_chunks;
|
|
void * m_chunk_ptr;
|
|
ptr_vector<void> m_free[NUM_FREE];
|
|
|
|
unsigned align_size(size_t sz) const {
|
|
return free_slot_id(sz) << PTR_ALIGNMENT;
|
|
}
|
|
unsigned free_slot_id(size_t size) const {
|
|
return (static_cast<unsigned>(size >> PTR_ALIGNMENT) + ((0 != (size & MASK)) ? 1u : 0u));
|
|
}
|
|
public:
|
|
sat_allocator(char const * id = "unknown"): m_id(id), m_alloc_size(0), m_chunk_ptr(nullptr) {}
|
|
~sat_allocator() { reset(); }
|
|
void reset() {
|
|
for (chunk * ch : m_chunks) dealloc(ch);
|
|
m_chunks.reset();
|
|
for (unsigned i = 0; i < NUM_FREE; ++i) m_free[i].reset();
|
|
m_alloc_size = 0;
|
|
m_chunk_ptr = nullptr;
|
|
}
|
|
void * allocate(size_t size) {
|
|
m_alloc_size += size;
|
|
if (size >= SMALL_OBJ_SIZE) {
|
|
return memory::allocate(size);
|
|
}
|
|
unsigned slot_id = free_slot_id(size);
|
|
if (!m_free[slot_id].empty()) {
|
|
void* result = m_free[slot_id].back();
|
|
m_free[slot_id].pop_back();
|
|
return result;
|
|
}
|
|
if (m_chunks.empty()) {
|
|
m_chunks.push_back(alloc(chunk));
|
|
m_chunk_ptr = m_chunks.back();
|
|
}
|
|
|
|
unsigned sz = align_size(size);
|
|
if ((char*)m_chunk_ptr + sz > (char*)m_chunks.back() + CHUNK_SIZE) {
|
|
m_chunks.push_back(alloc(chunk));
|
|
m_chunk_ptr = m_chunks.back();
|
|
}
|
|
void * result = m_chunk_ptr;
|
|
m_chunk_ptr = (char*)m_chunk_ptr + sz;
|
|
return result;
|
|
}
|
|
|
|
void deallocate(size_t size, void * p) {
|
|
m_alloc_size -= size;
|
|
if (size >= SMALL_OBJ_SIZE) {
|
|
memory::deallocate(p);
|
|
}
|
|
else {
|
|
m_free[free_slot_id(size)].push_back(p);
|
|
}
|
|
}
|
|
size_t get_allocation_size() const { return m_alloc_size; }
|
|
|
|
char const* id() const { return m_id; }
|
|
};
|
|
|
|
inline void * operator new(size_t s, sat_allocator & r) { return r.allocate(s); }
|
|
inline void * operator new[](size_t s, sat_allocator & r) { return r.allocate(s); }
|
|
inline void operator delete(void * p, sat_allocator & r) { UNREACHABLE(); }
|
|
inline void operator delete[](void * p, sat_allocator & r) { UNREACHABLE(); }
|
|
|
|
|