From 43671f36791a81ad903ab8b5f41ddf6c6a3dd754 Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Sat, 21 Sep 2024 11:56:19 +0200 Subject: [PATCH] concrete revisions not longer take space in the revision registry --- src/compiler/api/GF/Compile/ExampleBased.hs | 4 +- src/runtime/c/pgf/data.h | 4 -- src/runtime/c/pgf/db.cxx | 72 ++++++++++++++------- src/runtime/c/pgf/db.h | 11 ++-- src/runtime/c/pgf/namespace.h | 35 ++++++++++ src/runtime/c/pgf/pgf.cxx | 47 +++++++------- src/runtime/haskell/PGF2/FFI.hsc | 2 +- 7 files changed, 118 insertions(+), 57 deletions(-) diff --git a/src/compiler/api/GF/Compile/ExampleBased.hs b/src/compiler/api/GF/Compile/ExampleBased.hs index e07f79a5f0..1580b5937b 100644 --- a/src/compiler/api/GF/Compile/ExampleBased.hs +++ b/src/compiler/api/GF/Compile/ExampleBased.hs @@ -33,7 +33,7 @@ convertFile conf src file = do (ex, end) = break (=='"') (tail exend) in ((unwords (words cat),ex), tail end) -- quotes ignored pgf = resource_pgf conf - lang = language conf + lang = concrete conf convEx (cat,ex) = do appn "(" let typ = maybe (error "no valid cat") id $ readType cat @@ -61,7 +61,7 @@ convertFile conf src file = do data ExConfiguration = ExConf { resource_pgf :: PGF, verbose :: Bool, - language :: Concr, + concrete :: Concr, printExp :: Expr -> String } diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index ac8b5f447b..99ee8a427f 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -397,8 +397,6 @@ struct PGF_INTERNAL_DECL PgfLRState { }; struct PGF_INTERNAL_DECL PgfConcr { - static const uint8_t tag = 1; - Namespace cflags; Namespace lins; Namespace lincats; @@ -413,8 +411,6 @@ struct PGF_INTERNAL_DECL PgfConcr { }; struct PGF_INTERNAL_DECL PgfPGF { - static const uint8_t tag = 0; - uint16_t major_version; uint16_t minor_version; Namespace gflags; diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 444f0295f0..9e67a87f82 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -131,7 +131,7 @@ struct PGF_INTERNAL_DECL malloc_state object free_descriptors; size_t n_revisions; - object active_revision; + PgfRevision active_revision; revision_entry revisions[]; }; @@ -484,7 +484,7 @@ txn_t PgfDB::get_txn_id() { } PGF_INTERNAL -object PgfDB::register_revision(object o, txn_t txn_id) +PgfRevision PgfDB::register_revision(object o, txn_t txn_id) { #ifndef _WIN32 pthread_mutex_lock(&ms->rev_mutex); @@ -564,7 +564,7 @@ object PgfDB::register_revision(object o, txn_t txn_id) } PGF_INTERNAL -void PgfDB::unregister_revision(object revision) +PgfConcrRevision PgfDB::register_concr_revision(PgfRevision revision, size_t index) { if (revision == 0 || revision-1 >= ms->n_revisions) throw pgf_error("Invalid revision"); @@ -573,6 +573,40 @@ void PgfDB::unregister_revision(object revision) if (entry->ref_count == 0) throw pgf_error("Invalid revision"); + // The index must be at most 16 bits long + if (((index+1) & ((1 << 16) - 1)) != (index+1)) + throw pgf_error("Invalid revision"); + +#ifndef _WIN32 + pthread_mutex_lock(&ms->rev_mutex); +#else + WaitForSingleObject(hRevMutex, INFINITE); +#endif + + entry->ref_count++; + +#ifndef _WIN32 + pthread_mutex_unlock(&ms->rev_mutex); +#else + ReleaseMutex(hRevMutex); +#endif + + return revision | ((index+1) << 16); +} + +PGF_INTERNAL +void PgfDB::unregister_revision(PgfRevision revision) +{ + // Take a way the higher bits for a concrete revision + revision &= ((1 << 16) - 1); + + if (revision == 0 || revision-1 >= ms->n_revisions) + throw pgf_error("Invalid revision"); + + revision_entry *entry = &ms->revisions[revision-1]; + if (entry->ref_count == 0) + throw pgf_error("Invalid revision"); + #ifndef _WIN32 pthread_mutex_lock(&ms->rev_mutex); #else @@ -700,7 +734,7 @@ void PgfDB::cleanup_state() } PGF_INTERNAL -object PgfDB::get_active_revision() +PgfRevision PgfDB::get_active_revision() { return current_db->ms->active_revision; } @@ -1457,7 +1491,7 @@ void PgfDB::free_internal(object o, size_t bytes) } PGF_INTERNAL -ref PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id) +ref PgfDB::revision2pgf(PgfRevision revision) { if (revision == 0 || revision-1 >= ms->n_revisions) throw pgf_error("Invalid revision"); @@ -1466,22 +1500,18 @@ ref PgfDB::revision2pgf(PgfRevision revision, size_t *p_txn_id) if (entry->ref_count == 0) throw pgf_error("Invalid revision"); - if (ref::get_tag(entry->o) != PgfPGF::tag) - throw pgf_error("Invalid revision"); - - ref pgf = ref::untagged(entry->o); - if (pgf.as_object() >= top) + if (entry->o >= top) throw pgf_error("Invalid revision"); - if (p_txn_id != NULL) - *p_txn_id = entry->txn_id; - - return pgf; + return entry->o; } PGF_INTERNAL -ref PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id) +ref PgfDB::revision2concr(PgfConcrRevision concr_revision) { + PgfRevision revision = concr_revision & ((1 << 16) - 1); + size_t index = concr_revision >> 16; + if (revision == 0 || revision-1 >= ms->n_revisions) throw pgf_error("Invalid revision"); @@ -1489,16 +1519,14 @@ ref PgfDB::revision2concr(PgfConcrRevision revision, size_t *p_txn_id) if (entry->ref_count == 0) throw pgf_error("Invalid revision"); - if (ref::get_tag(entry->o) != PgfConcr::tag) + ref pgf = entry->o; + if (pgf.as_object() >= top) throw pgf_error("Invalid revision"); - ref concr = ref::untagged(entry->o); - if (concr.as_object() >= top) + ref concr = namespace_index(pgf->concretes, index-1); + if (concr == 0) throw pgf_error("Invalid revision"); - if (p_txn_id != NULL) - *p_txn_id = entry->txn_id; - return concr; } @@ -1558,7 +1586,7 @@ void PgfDB::commit(object o) object save_top = ms->top; object save_free_blocks = ms->free_blocks; object save_free_descriptors = ms->free_descriptors; - object save_active_revision = ms->active_revision; + PgfRevision save_active_revision = ms->active_revision; #ifndef _WIN32 int res; diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index 760437d70e..7f0472be42 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -124,12 +124,13 @@ class PgfDB { current_db->free_internal(o.as_object(), sizeof(A)+extra_bytes); } - PGF_INTERNAL_DECL object get_active_revision(); - PGF_INTERNAL_DECL object register_revision(object o, txn_t txn_id); - PGF_INTERNAL_DECL void unregister_revision(object o); + PGF_INTERNAL_DECL PgfRevision get_active_revision(); + PGF_INTERNAL_DECL PgfRevision register_revision(object o, txn_t txn_id); + PGF_INTERNAL_DECL PgfConcrRevision register_concr_revision(PgfRevision revision, size_t index); + PGF_INTERNAL_DECL void unregister_revision(PgfRevision o); - PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision, size_t *p_txn_id = NULL); - PGF_INTERNAL_DECL ref revision2concr(PgfConcrRevision revision, size_t *p_txn_id = NULL); + PGF_INTERNAL_DECL ref revision2pgf(PgfRevision revision); + PGF_INTERNAL_DECL ref revision2concr(PgfConcrRevision concr_revision); PGF_INTERNAL_DECL void start_transaction(); PGF_INTERNAL_DECL void set_transaction_object(object o); diff --git a/src/runtime/c/pgf/namespace.h b/src/runtime/c/pgf/namespace.h index 3d40470f8b..4284f246db 100644 --- a/src/runtime/c/pgf/namespace.h +++ b/src/runtime/c/pgf/namespace.h @@ -606,6 +606,41 @@ ref namespace_lookup(Namespace map, PgfText *name) return 0; } +template +ref namespace_lookup_index(Namespace map, PgfText *name, size_t *pIndex) +{ + *pIndex = 0; + while (map != 0) { + int cmp = textcmp(name,&map->value->name); + if (cmp < 0) { + map = map->left; + } else if (cmp > 0) { + map = map->right; + *pIndex += Node>::size(map->left)+1; + } else { + return map->value; + } + } + return 0; +} + +template +ref namespace_index(Namespace map, size_t index) +{ + while (map != 0) { + size_t sz = Node>::size(map->left); + if (index < sz) { + map = map->left; + } else if (index > sz) { + map = map->right; + index -= sz+1; + } else { + return map->value; + } + } + return 0; +} + template size_t namespace_size(Namespace map) { diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index cc621b725b..6a332a2956 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -71,7 +71,7 @@ PgfDB *pgf_read_pgf(const char* fpath, PgfRevision *revision, db->set_transaction_object(pgf.as_object()); - *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); + *revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -126,7 +126,7 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, db->set_transaction_object(pgf.as_object()); - *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); + *revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -199,7 +199,7 @@ PgfDB *pgf_boot_ngf_cookie(void *cookie, db->set_transaction_object(pgf.as_object()); - *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); + *revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -234,7 +234,7 @@ PgfDB *pgf_read_ngf(const char *fpath, ref pgf = db->get_active_revision(); *revision = 0; if (pgf != 0) { - *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()-1); + *revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()-1); db->ref_count++; } } @@ -284,7 +284,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name, db->set_transaction_object(pgf.as_object()); - *revision = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()); + *revision = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()); db->commit(pgf.as_object()); } @@ -469,14 +469,14 @@ void pgf_iter_concretes(PgfDB *db, PgfRevision revision, PgfItor *itor, PgfExn *err) { PGF_API_BEGIN { - size_t txn_id; - DB_scope scope(db, READER_SCOPE); - ref pgf = db->revision2pgf(revision, &txn_id); + ref pgf = db->revision2pgf(revision); + size_t index = 0; std::function)> f = - [txn_id,db,itor,err](ref concr) { - object rev = db->register_revision(concr.tagged(), txn_id); + [db,revision,itor,err,&index](ref concr) { + PgfConcrRevision rev = db->register_concr_revision(revision, index); + index++; db->ref_count++; itor->fn(itor, &concr->name, rev, err); return (err->type == PGF_EXN_NONE); @@ -490,18 +490,17 @@ PgfConcrRevision pgf_get_concrete(PgfDB *db, PgfRevision revision, PgfText *name, PgfExn *err) { PGF_API_BEGIN { - size_t txn_id; - DB_scope scope(db, READER_SCOPE); - ref pgf = db->revision2pgf(revision, &txn_id); + ref pgf = db->revision2pgf(revision); + size_t index; ref concr = - namespace_lookup(pgf->concretes, name); + namespace_lookup_index(pgf->concretes, name, &index); if (concr == 0) return 0; db->ref_count++; - return db->register_revision(concr.tagged(), txn_id); + return db->register_concr_revision(revision, index); } PGF_API_END return 0; @@ -1425,7 +1424,7 @@ PgfRevision pgf_start_transaction(PgfDB *db, PgfExn *err) db->set_transaction_object(new_pgf.as_object()); - object rev = db->register_revision(new_pgf.tagged(), PgfDB::get_txn_id()); + object rev = db->register_revision(new_pgf.as_object(), PgfDB::get_txn_id()); PgfDB::free(pgf); @@ -1456,7 +1455,7 @@ PgfRevision pgf_checkout_revision(PgfDB *db, PgfExn *err) ref pgf = db->get_active_revision(); object rev = 0; if (pgf != 0) { - rev = db->register_revision(pgf.tagged(), PgfDB::get_txn_id()-1); + rev = db->register_revision(pgf.as_object(), PgfDB::get_txn_id()-1); db->ref_count++; } return rev; @@ -1689,8 +1688,9 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision, ref pgf = db->revision2pgf(revision); + size_t index; ref concr = - namespace_lookup(pgf->concretes, name); + namespace_lookup_index(pgf->concretes, name, &index); if (concr != 0) throw pgf_error("The concrete syntax already exists"); @@ -1702,8 +1702,6 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision, concr->printnames = 0; memcpy(&concr->name, name, sizeof(PgfText)+name->size+1); - object rev = db->register_revision(concr.tagged(), PgfDB::get_txn_id()); - Namespace concrs = namespace_insert(pgf->concretes, concr); if (concrs == 0) { @@ -1711,6 +1709,8 @@ PgfConcrRevision pgf_create_concrete(PgfDB *db, PgfRevision revision, } pgf->concretes = concrs; + object rev = db->register_concr_revision(revision, index); + db->ref_count++; return rev; } PGF_API_END @@ -1726,15 +1726,16 @@ PgfConcrRevision pgf_clone_concrete(PgfDB *db, PgfRevision revision, DB_scope scope(db, WRITER_SCOPE); ref pgf = db->revision2pgf(revision); - + + size_t index; ref concr = - namespace_lookup(pgf->concretes, name); + namespace_lookup_index(pgf->concretes, name, &index); if (concr == 0) throw pgf_error("Unknown concrete syntax"); concr = clone_concrete(pgf, concr); - object rev = db->register_revision(concr.tagged(), PgfDB::get_txn_id()); + object rev = db->register_concr_revision(revision, index); db->ref_count++; return rev; } PGF_API_END diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 3278c2f320..2030846bd9 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -178,7 +178,7 @@ foreign import ccall pgf_iter_categories :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor foreign import ccall pgf_iter_concretes :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor -> Ptr PgfExn -> IO () -foreign import ccall pgf_get_concrete :: Ptr PgfDB -> Ptr PGF -> Ptr PgfItor -> Ptr PgfExn -> IO (Ptr Concr) +foreign import ccall pgf_get_concrete :: Ptr PgfDB -> Ptr PGF -> Ptr PgfText -> Ptr PgfExn -> IO (Ptr Concr) foreign import ccall pgf_start_cat :: Ptr PgfDB -> Ptr PGF -> Ptr PgfUnmarshaller -> Ptr PgfExn -> IO (StablePtr Type)