3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

Merge pull request #722 from wintersteiger/i715

x64 clause allocator bug fix
This commit is contained in:
Christoph M. Wintersteiger 2016-09-16 19:53:08 +01:00 committed by GitHub
commit 7a3308110c
2 changed files with 46 additions and 55 deletions

View file

@ -125,9 +125,6 @@ namespace sat {
m_allocator("clause-allocator") { m_allocator("clause-allocator") {
#if defined(_AMD64_) #if defined(_AMD64_)
m_num_segments = 0; m_num_segments = 0;
#if defined(Z3DEBUG)
m_overflow_valid = false;
#endif
#endif #endif
} }
@ -135,11 +132,14 @@ namespace sat {
#if defined(_AMD64_) #if defined(_AMD64_)
#if defined (Z3DEBUG) #if defined (Z3DEBUG)
clause const* result; clause const* result;
if (m_overflow_valid && m_cls_offset2ptr.find(cls_off, result)) { if (((cls_off & c_alignment_mask) == c_last_segment)) {
unsigned id = cls_off >> c_cls_alignment;
bool check = m_last_seg_id2cls.find(id, result);
SASSERT(check);
return const_cast<clause*>(result); return const_cast<clause*>(result);
} }
#endif #endif
return reinterpret_cast<clause *>(m_segments[cls_off & c_aligment_mask] + (static_cast<size_t>(cls_off) & ~c_aligment_mask)); return reinterpret_cast<clause *>(m_segments[cls_off & c_alignment_mask] + (static_cast<size_t>(cls_off) & ~c_alignment_mask));
#else #else
return reinterpret_cast<clause *>(cls_off); return reinterpret_cast<clause *>(cls_off);
#endif #endif
@ -149,59 +149,53 @@ namespace sat {
unsigned clause_allocator::get_segment(clause const* cls) { unsigned clause_allocator::get_segment(clause const* cls) {
size_t ptr = reinterpret_cast<size_t>(cls); size_t ptr = reinterpret_cast<size_t>(cls);
SASSERT((ptr & c_aligment_mask) == 0); SASSERT((ptr & c_alignment_mask) == 0);
ptr &= ~0xFFFFFFFFull; // Keep only high part ptr &= 0xFFFFFFFF00000000ull; // Keep only high part
unsigned i = 0; unsigned i = 0;
for (i = 0; i < m_num_segments; ++i) for (i = 0; i < m_num_segments; ++i)
if (m_segments[i] == ptr) if (m_segments[i] == ptr)
return i; return i;
i = m_num_segments; i = m_num_segments;
SASSERT(i <= c_last_segment);
#if defined(Z3DEBUG) #if defined(Z3DEBUG)
SASSERT(i < c_max_segments); if (i == c_last_segment) {
if (i + 1 == c_max_segments) { if (!m_last_seg_id2cls.contains(cls->id()))
m_overflow_valid = true; m_last_seg_id2cls.insert(cls->id(), cls);
i += c_max_segments * m_cls_offset2ptr.size();
m_ptr2cls_offset.insert(ptr, i);
m_cls_offset2ptr.insert(i, cls);
} }
else { else {
++m_num_segments; ++m_num_segments;
m_segments[i] = ptr; m_segments[i] = ptr;
} }
#else #else
SASSERT(i <= c_max_segments); if (i == c_last_segment) {
if (i == c_max_segments) {
throw default_exception("segment out of range"); throw default_exception("segment out of range");
} }
m_segments[i] = ptr; m_segments[i] = ptr;
++m_num_segments; ++m_num_segments;
#endif #endif
return i; return i;
} }
#endif #endif
clause_offset clause_allocator::get_offset(clause const * ptr) const { clause_offset clause_allocator::get_offset(clause const * cls) const {
#if defined(_AMD64_) #if defined(_AMD64_)
unsigned segment = const_cast<clause_allocator*>(this)->get_segment(ptr); unsigned segment = const_cast<clause_allocator*>(this)->get_segment(cls);
#if defined(Z3DEBUG) #if defined(Z3DEBUG)
if (segment >= c_max_segments) { SASSERT(segment <= c_last_segment);
return m_ptr2cls_offset.find(reinterpret_cast<size_t>(ptr)); if (segment == c_last_segment) {
SASSERT(m_last_seg_id2cls.contains(cls->id()));
return (cls->id() << c_cls_alignment) | c_last_segment;
} }
#endif #endif
return static_cast<unsigned>(reinterpret_cast<size_t>(ptr)) + segment; return static_cast<unsigned>(reinterpret_cast<size_t>(cls)) + segment;
#else #else
return reinterpret_cast<size_t>(ptr); return reinterpret_cast<size_t>(cls);
#endif #endif
} }
clause * clause_allocator::mk_clause(unsigned num_lits, literal const * lits, bool learned) { clause * clause_allocator::mk_clause(unsigned num_lits, literal const * lits, bool learned) {
size_t size = clause::get_obj_size(num_lits); size_t size = clause::get_obj_size(num_lits);
#if defined(_AMD64_)
size_t slot = size >> c_cls_alignment;
if ((size & c_aligment_mask) != 0)
slot++;
size = slot << c_cls_alignment;
#endif
void * mem = m_allocator.allocate(size); void * mem = m_allocator.allocate(size);
clause * cls = new (mem) clause(m_id_gen.mk(), num_lits, lits, learned); clause * cls = new (mem) clause(m_id_gen.mk(), num_lits, lits, learned);
TRACE("sat", tout << "alloc: " << cls->id() << " " << cls << " " << *cls << " " << (learned?"l":"a") << "\n";); TRACE("sat", tout << "alloc: " << cls->id() << " " << cls << " " << *cls << " " << (learned?"l":"a") << "\n";);
@ -212,13 +206,12 @@ namespace sat {
void clause_allocator::del_clause(clause * cls) { void clause_allocator::del_clause(clause * cls) {
TRACE("sat", tout << "delete: " << cls->id() << " " << cls << " " << *cls << "\n";); TRACE("sat", tout << "delete: " << cls->id() << " " << cls << " " << *cls << "\n";);
m_id_gen.recycle(cls->id()); m_id_gen.recycle(cls->id());
size_t size = clause::get_obj_size(cls->m_capacity);
#if defined(_AMD64_) #if defined(_AMD64_)
size_t slot = size >> c_cls_alignment; #if defined(Z3DEBUG)
if ((size & c_aligment_mask) != 0) m_last_seg_id2cls.remove(cls->id());
slot++;
size = slot << c_cls_alignment;
#endif #endif
#endif
size_t size = clause::get_obj_size(cls->m_capacity);
cls->~clause(); cls->~clause();
m_allocator.deallocate(size, cls); m_allocator.deallocate(size, cls);
} }

View file

@ -128,14 +128,12 @@ namespace sat {
#if defined(_AMD64_) #if defined(_AMD64_)
unsigned get_segment(clause const* cls); unsigned get_segment(clause const* cls);
static const unsigned c_cls_alignment = 3; static const unsigned c_cls_alignment = 3;
static const unsigned c_max_segments = 1 << c_cls_alignment; static const unsigned c_last_segment = (1ull << c_cls_alignment) - 1ull;
static const size_t c_aligment_mask = (1ull << c_cls_alignment) - 1ull; static const size_t c_alignment_mask = (1ull << c_cls_alignment) - 1ull;
unsigned m_num_segments; unsigned m_num_segments;
size_t m_segments[c_max_segments]; size_t m_segments[c_last_segment];
#if defined(Z3DEBUG) #if defined(Z3DEBUG)
bool m_overflow_valid; u_map<clause const*> m_last_seg_id2cls;
size_t_map<unsigned> m_ptr2cls_offset;
u_map<clause const*> m_cls_offset2ptr;
#endif #endif
#endif #endif
public: public: