mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
more bugfixes in the allocator
This commit is contained in:
@@ -1027,29 +1027,32 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
||||
fit:
|
||||
*po = descr->o;
|
||||
|
||||
object new_map;
|
||||
if (descr->left == 0) {
|
||||
new_map = descr->right;
|
||||
} else if (descr->right == 0) {
|
||||
new_map = descr->left;
|
||||
} else {
|
||||
if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) {
|
||||
object right = descr->right;
|
||||
object left = pop_last_block_descriptor(descr->left, &new_map);
|
||||
new_map = upd_block_descr(new_map, left, right);
|
||||
new_map = balanceR_block_descriptor(new_map);
|
||||
} else {
|
||||
object left = descr->left;
|
||||
object right = pop_first_block_descriptor(descr->right, &new_map);
|
||||
new_map = upd_block_descr(new_map, left, right);
|
||||
new_map = balanceL_block_descriptor(new_map);
|
||||
}
|
||||
}
|
||||
|
||||
int index = (descr->descr_txn_id != ms->curr_txn_id);
|
||||
descr->chain = free_descriptors[index];
|
||||
free_descriptors[index] = map;
|
||||
if (index == 1 && free_descriptors[2] == 0)
|
||||
free_descriptors[2] = map;
|
||||
|
||||
if (descr->left == 0) {
|
||||
return descr->right;
|
||||
} else if (descr->right == 0) {
|
||||
return descr->left;
|
||||
} else {
|
||||
if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) {
|
||||
object right = descr->right;
|
||||
object left = pop_last_block_descriptor(descr->left, &map);
|
||||
map = upd_block_descr(map, left, right);
|
||||
return balanceR_block_descriptor(map);
|
||||
} else {
|
||||
object left = descr->left;
|
||||
object right = pop_first_block_descriptor(descr->right, &map);
|
||||
map = upd_block_descr(map, left, right);
|
||||
return balanceL_block_descriptor(map);
|
||||
}
|
||||
}
|
||||
return new_map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1125,7 +1128,7 @@ object PgfDB::malloc_internal(size_t bytes)
|
||||
}
|
||||
|
||||
PGF_INTERNAL
|
||||
object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes)
|
||||
object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id)
|
||||
{
|
||||
if (oldo == 0)
|
||||
return malloc_internal(new_bytes);
|
||||
@@ -1133,31 +1136,36 @@ object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes)
|
||||
size_t old_nb = request2size(old_bytes);
|
||||
size_t new_nb = request2size(new_bytes);
|
||||
|
||||
if (oldo + old_nb == top) {
|
||||
ssize_t nb = new_nb-old_nb;
|
||||
ssize_t free_size = mmap_size - top;
|
||||
if (txn_id == ms->curr_txn_id) {
|
||||
if (old_nb == new_nb)
|
||||
return oldo;
|
||||
|
||||
if (nb > free_size) {
|
||||
size_t alloc_size =
|
||||
((nb - free_size + page_size - 1) / page_size) * page_size;
|
||||
size_t new_size =
|
||||
ms->file_size + alloc_size;
|
||||
if (oldo + old_nb == top) {
|
||||
ssize_t nb = new_nb-old_nb;
|
||||
ssize_t free_size = mmap_size - top;
|
||||
|
||||
resize_map(new_size);
|
||||
}
|
||||
if (nb > free_size) {
|
||||
size_t alloc_size =
|
||||
((nb - free_size + page_size - 1) / page_size) * page_size;
|
||||
size_t new_size =
|
||||
ms->file_size + alloc_size;
|
||||
|
||||
// If the object is at the end of the allocation area
|
||||
top += nb;
|
||||
resize_map(new_size);
|
||||
}
|
||||
|
||||
// If the object is at the end of the allocation area
|
||||
top += nb;
|
||||
|
||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
||||
fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes);
|
||||
fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes);
|
||||
#endif
|
||||
|
||||
return oldo;
|
||||
return oldo;
|
||||
}
|
||||
}
|
||||
|
||||
object newo = malloc_internal(new_bytes);
|
||||
memcpy(base+newo, base+oldo, old_bytes < new_bytes ? old_bytes : new_bytes);
|
||||
memcpy(base+newo, base+oldo, (old_bytes < new_bytes) ? old_bytes : new_bytes);
|
||||
free_internal(oldo, old_bytes);
|
||||
return newo;
|
||||
}
|
||||
|
||||
@@ -103,8 +103,8 @@ public:
|
||||
}
|
||||
|
||||
template<class A>
|
||||
static ref<A> realloc(ref<A> r, size_t old_extra_bytes, size_t new_extra_bytes) {
|
||||
return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes);
|
||||
static ref<A> realloc(ref<A> r, size_t old_extra_bytes, size_t new_extra_bytes, txn_t txn_id) {
|
||||
return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes, txn_id);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
@@ -144,7 +144,7 @@ private:
|
||||
|
||||
PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
|
||||
|
||||
PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes);
|
||||
PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id);
|
||||
|
||||
PGF_INTERNAL_DECL void free_internal(object o, size_t bytes);
|
||||
|
||||
|
||||
@@ -1847,7 +1847,7 @@ public:
|
||||
|
||||
size_t len = entry->backrefs->len;
|
||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
||||
vector_unsafe_resize<PgfSequenceBackref>(entry->backrefs, len+1);
|
||||
vector_resize<PgfSequenceBackref>(entry->backrefs, len+1, PgfDB::get_txn_id());
|
||||
backrefs->data[len].container = container;
|
||||
backrefs->data[len].seq_index = seq_index;
|
||||
entry->backrefs = backrefs;
|
||||
|
||||
@@ -270,13 +270,12 @@ PgfPhrasetable phrasetable_internalize(PgfPhrasetable table,
|
||||
: 0;
|
||||
|
||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
||||
vector_copy<PgfSequenceBackref>(table->value.backrefs, len+1);
|
||||
vector_resize<PgfSequenceBackref>(table->value.backrefs, len+1, table->txn_id);
|
||||
backrefs->data[len].container = container;
|
||||
backrefs->data[len].seq_index = seq_index;
|
||||
|
||||
PgfPhrasetable new_table =
|
||||
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
||||
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
|
||||
new_table->value.backrefs = backrefs;
|
||||
*pentry = ref<PgfPhrasetableEntry>::from_ptr(&new_table->value);
|
||||
return new_table;
|
||||
@@ -299,7 +298,7 @@ ref<PgfSequence> phrasetable_relink(PgfPhrasetable table,
|
||||
: table->value.backrefs->len;
|
||||
|
||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
||||
vector_unsafe_resize<PgfSequenceBackref>(table->value.backrefs, len+1);
|
||||
vector_resize<PgfSequenceBackref>(table->value.backrefs, len+1, table->txn_id);
|
||||
backrefs->data[len].container = container;
|
||||
backrefs->data[len].seq_index = seq_index;
|
||||
table->value.backrefs = backrefs;
|
||||
@@ -342,29 +341,25 @@ PgfPhrasetable phrasetable_delete(PgfPhrasetable table,
|
||||
size_t len = table->value.backrefs->len;
|
||||
if (len > 1) {
|
||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
||||
vector_new<PgfSequenceBackref>(len-1);
|
||||
vector_resize<PgfSequenceBackref>(table->value.backrefs, len-1, table->txn_id);
|
||||
size_t i = 0;
|
||||
while (i < len) {
|
||||
ref<PgfSequenceBackref> backref =
|
||||
vector_elem(table->value.backrefs, i);
|
||||
ref<PgfSequenceBackref> backref =
|
||||
vector_elem(backrefs, i);
|
||||
if (backref->container == container &&
|
||||
backref->seq_index == seq_index) {
|
||||
break;
|
||||
}
|
||||
*vector_elem(backrefs, i) = *backref;
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
while (i < len) {
|
||||
ref<PgfSequenceBackref> backref =
|
||||
vector_elem(table->value.backrefs, i);
|
||||
*vector_elem(backrefs, i-1) = *backref;
|
||||
*vector_elem(backrefs, i-1) = *vector_elem(backrefs, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
PgfPhrasetable new_table =
|
||||
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
||||
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
|
||||
new_table->value.backrefs = backrefs;
|
||||
return new_table;
|
||||
} else {
|
||||
|
||||
@@ -31,55 +31,20 @@ ref<C> vector_new(Vector<A> C::* field, size_t len)
|
||||
PGF_INTERNAL_DECL size_t
|
||||
get_next_padovan(size_t min);
|
||||
|
||||
/* Resize a vector by creating a new one and copying the old content.
|
||||
* The new vector is now also safe to update */
|
||||
template <class A> inline PGF_INTERNAL
|
||||
ref<Vector<A>> vector_copy(ref<Vector<A>> vec, size_t len)
|
||||
{
|
||||
size_t size = len*sizeof(A);
|
||||
ref<Vector<A>> res = PgfDB::malloc<Vector<A>>(size);
|
||||
res->len = len;
|
||||
memcpy(res->data, vec->data, size);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Resize a vector by changing its length. If there is no enough space
|
||||
* the implementation will create a copy, but whenever possible it will
|
||||
* return the reference of the original vector. In the later case, it
|
||||
* changes the length in-place which means that the function is safe
|
||||
* only if the vector was created during the current transaction. */
|
||||
* return the reference to the original vector. A copy is created also
|
||||
* if txn_id is different from the current transaction. In this way
|
||||
* it is safe to change the length. */
|
||||
template <class A> inline PGF_INTERNAL
|
||||
ref<Vector<A>> vector_unsafe_resize(ref<Vector<A>> vec, size_t len)
|
||||
ref<Vector<A>> vector_resize(ref<Vector<A>> vec, size_t len, txn_t txn_id)
|
||||
{
|
||||
size_t new_len = get_next_padovan(len);
|
||||
size_t old_len = get_next_padovan(vec->len);
|
||||
size_t new_len = get_next_padovan(len);
|
||||
|
||||
if (old_len == new_len)
|
||||
return vec;
|
||||
|
||||
ref<Vector<A>> res = PgfDB::realloc<Vector<A>>(vec,old_len*sizeof(A),new_len*sizeof(A)).as_object();
|
||||
res->len = len;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Resize a vector embedded in another structure, by changing its length.
|
||||
* If there is no enough space the implementation will copy the structure,
|
||||
* but whenever possible it will return a reference to
|
||||
* the original structure. In the later case, it changes
|
||||
* the vector's length in-place which means that the function is safe
|
||||
* only if the structure was created during the current transaction. */
|
||||
template <class C, class A> inline PGF_INTERNAL
|
||||
ref<C> vector_unsafe_resize(ref<C> r, Vector<A> C::* field, size_t len)
|
||||
{
|
||||
size_t old_len = get_next_padovan((r->*field).len);
|
||||
size_t new_len = get_next_padovan(len);
|
||||
|
||||
if (old_len == new_len)
|
||||
return r;
|
||||
|
||||
ref<C> res = PgfDB::realloc<C>(r,old_len*sizeof(A),new_len*sizeof(A)).as_object();
|
||||
(res->*field).len = len;
|
||||
return res;
|
||||
vec = PgfDB::realloc<Vector<A>>(vec,old_len*sizeof(A),new_len*sizeof(A),txn_id);
|
||||
vec->len = len;
|
||||
return vec;
|
||||
}
|
||||
|
||||
template <class A> inline PGF_INTERNAL
|
||||
|
||||
Reference in New Issue
Block a user